From 765020c320a8fb75c062c9a7286f7864b909e8d6 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Tue, 13 Aug 2024 17:14:12 +0200
Subject: [PATCH 01/81] Fix: tx-details redesign fixes (#4059)
* Fix: for approvals, move method call to advanced details
* Fix: restore "native transfer"; wrap "Interacted with" (#4060)
* Approval check
* FieldsGrid wrap
---
src/components/tx/DecodedTx/index.tsx | 1 +
src/components/tx/FieldsGrid/index.tsx | 5 +++--
src/components/tx/SignOrExecuteForm/index.tsx | 7 +++++--
3 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/src/components/tx/DecodedTx/index.tsx b/src/components/tx/DecodedTx/index.tsx
index 3cf55b1043..d6c2d96429 100644
--- a/src/components/tx/DecodedTx/index.tsx
+++ b/src/components/tx/DecodedTx/index.tsx
@@ -87,6 +87,7 @@ const DecodedTx = ({
{isMethodCallInAdvanced && decodedData?.method}
+ {!showMethodCall && !decodedData?.method && tx?.data.value && 'native transfer'}
diff --git a/src/components/tx/FieldsGrid/index.tsx b/src/components/tx/FieldsGrid/index.tsx
index 2f724189f1..36c1e4f475 100644
--- a/src/components/tx/FieldsGrid/index.tsx
+++ b/src/components/tx/FieldsGrid/index.tsx
@@ -1,11 +1,12 @@
import { type ReactNode } from 'react'
import { Grid, Typography } from '@mui/material'
-const minWidth = { xl: '25%', lg: '2vw' }
+const minWidth = { xl: '25%', lg: '100px' }
+const wrap = { flexWrap: { xl: 'nowrap' } }
const FieldsGrid = ({ title, children }: { title: string; children: ReactNode }) => {
return (
-
+
{title}
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index fb829a1825..326da17b40 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -35,6 +35,7 @@ import { TwapFallbackHandlerWarning } from '@/features/swap/components/TwapFallb
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
import useTxDetails from '@/hooks/useTxDetails'
import TxData from '@/components/transactions/TxDetails/TxData'
+import { useApprovalInfos } from '../ApprovalEditor/hooks/useApprovalInfos'
export type SubmitCallback = (txId: string, isExecuted?: boolean) => void
@@ -94,6 +95,8 @@ export const SignOrExecuteForm = ({
const isSwapOrder = isConfirmationViewOrder(decodedData)
const [txDetails] = useTxDetails(props.txId)
const showTxDetails = props.txId && txDetails && !isCustomTxInfo(txDetails.txInfo)
+ const [readableApprovals] = useApprovalInfos({ safeTransaction: safeTx })
+ const isApproval = readableApprovals && readableApprovals.length > 0
const { safe } = useSafeInfo()
const isSafeOwner = useIsSafeOwner()
@@ -144,7 +147,7 @@ export const SignOrExecuteForm = ({
)}
Error parsing data}>
-
+ {isApproval && }
{showTxDetails && }
@@ -153,7 +156,7 @@ export const SignOrExecuteForm = ({
txId={props.txId}
decodedData={decodedData}
showMultisend={!props.isBatch}
- showMethodCall={props.showMethodCall && !showTxDetails && !isSwapOrder}
+ showMethodCall={props.showMethodCall && !showTxDetails && !isSwapOrder && !isApproval}
/>
From 0b1e51c63ef101dba5ef5134bd54db041bf9b5de Mon Sep 17 00:00:00 2001
From: James Mealy
Date: Wed, 14 Aug 2024 09:19:38 +0200
Subject: [PATCH 02/81] Feat: create a dashboard banner to enable user accounts
with SIWE (#3997)
* add create account function
* feat: add enable sign in banner
* feat: make banner dismissable
* rename banner
* update siging message
* Use createAccount and getAccount from gateway-sdk
* Add banner to storybook, remove from dashboard
* fix: use logError
* Update src/services/exceptions/ErrorCodes.ts
Co-authored-by: katspaugh <381895+katspaugh@users.noreply.github.com>
---------
Co-authored-by: katspaugh <381895+katspaugh@users.noreply.github.com>
---
public/images/common/download-cloud.svg | 12 +++
.../EnableAccountBanner/index.stories.tsx | 37 ++++++++++
.../components/EnableAccountBanner/index.tsx | 73 +++++++++++++++++++
.../EnableAccountBanner/style.module.css | 11 +++
src/services/exceptions/ErrorCodes.ts | 2 +
src/services/siwe/index.ts | 7 +-
6 files changed, 138 insertions(+), 4 deletions(-)
create mode 100644 public/images/common/download-cloud.svg
create mode 100644 src/features/siweAccounts/components/EnableAccountBanner/index.stories.tsx
create mode 100644 src/features/siweAccounts/components/EnableAccountBanner/index.tsx
create mode 100644 src/features/siweAccounts/components/EnableAccountBanner/style.module.css
diff --git a/public/images/common/download-cloud.svg b/public/images/common/download-cloud.svg
new file mode 100644
index 0000000000..b6dd6403cc
--- /dev/null
+++ b/public/images/common/download-cloud.svg
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/features/siweAccounts/components/EnableAccountBanner/index.stories.tsx b/src/features/siweAccounts/components/EnableAccountBanner/index.stories.tsx
new file mode 100644
index 0000000000..223aae84c9
--- /dev/null
+++ b/src/features/siweAccounts/components/EnableAccountBanner/index.stories.tsx
@@ -0,0 +1,37 @@
+import type { Meta, StoryObj } from '@storybook/react'
+import EnableAccountBanner from './index'
+import { Paper } from '@mui/material'
+import type { Eip1193Provider } from 'ethers'
+import { BrowserProvider } from 'ethers'
+
+const mockBrowserProvider = new BrowserProvider({
+ request: () => {},
+} as unknown as Eip1193Provider)
+
+const meta = {
+ component: EnableAccountBanner,
+ parameters: {
+ layout: 'centered',
+ },
+ decorators: [
+ (Story) => {
+ return (
+
+
+
+ )
+ },
+ ],
+
+ tags: ['autodocs'],
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+// More on writing stories with args: https://storybook.js.org/docs/writing-stories/args
+export const Default: Story = {
+ args: {
+ provider: mockBrowserProvider,
+ },
+}
diff --git a/src/features/siweAccounts/components/EnableAccountBanner/index.tsx b/src/features/siweAccounts/components/EnableAccountBanner/index.tsx
new file mode 100644
index 0000000000..126c3d750b
--- /dev/null
+++ b/src/features/siweAccounts/components/EnableAccountBanner/index.tsx
@@ -0,0 +1,73 @@
+import { signInWithEthereum } from '@/services/siwe'
+import { Alert, Box, Button, IconButton, Typography } from '@mui/material'
+import useWallet from '@/hooks/wallets/useWallet'
+import CloseIcon from '@mui/icons-material/Close'
+import DownloadCloud from '@/public/images/common/download-cloud.svg'
+import ChevronRightIcon from '@mui/icons-material/ChevronRight'
+
+import css from './style.module.css'
+import { useState } from 'react'
+import { createAccount, getAccount } from '@safe-global/safe-gateway-typescript-sdk'
+import type { BrowserProvider } from 'ethers'
+import { logError } from '@/services/exceptions'
+import ErrorCodes from '@/services/exceptions/ErrorCodes'
+
+const SignInBanner = ({ provider }: { provider: BrowserProvider | undefined }) => {
+ const { address = '' } = useWallet() || {}
+ const [isDismissed, setIsDismissed] = useState(false)
+
+ if (!provider || isDismissed) return null
+
+ const signIn = async () => {
+ let account
+ try {
+ await signInWithEthereum(provider)
+ account = await getAccount(address)
+ } catch (error) {
+ logError(ErrorCodes._640, error)
+ }
+ if (!account) {
+ try {
+ account = await createAccount({ address: address as `0x${string}` })
+ } catch (error) {
+ logError(ErrorCodes._641, error)
+ }
+ }
+ }
+
+ return (
+
+
}
+ action={
+ <>
+
} sx={{ padding: '2px', minWidth: '130px' }}>
+
+ Enable now
+
+
+
{
+ setIsDismissed(true)
+ }}
+ >
+
+
+ >
+ }
+ >
+
+
+ Access your accounts on any device! Enable cloud storage to switch devices effortlessly and keep your
+ data secure.
+
+
+
+
+ )
+}
+
+export default SignInBanner
diff --git a/src/features/siweAccounts/components/EnableAccountBanner/style.module.css b/src/features/siweAccounts/components/EnableAccountBanner/style.module.css
new file mode 100644
index 0000000000..075c499000
--- /dev/null
+++ b/src/features/siweAccounts/components/EnableAccountBanner/style.module.css
@@ -0,0 +1,11 @@
+.container :global .MuiAlert-message {
+ padding: 4px;
+}
+
+.container :global .MuiAlert-action {
+ padding-top: 2px;
+}
+
+.container :global .MuiAlert-root {
+ border: 1px solid var(--color-secondary-light);
+}
diff --git a/src/services/exceptions/ErrorCodes.ts b/src/services/exceptions/ErrorCodes.ts
index be96e60985..b2b380d7db 100644
--- a/src/services/exceptions/ErrorCodes.ts
+++ b/src/services/exceptions/ErrorCodes.ts
@@ -42,6 +42,8 @@ enum ErrorCodes {
_631 = '631: Transaction failed to be relayed',
_632 = '632: Error fetching relay task status',
_633 = '633: Notification (un-)registration failed',
+ _640 = '640: User account not found',
+ _641 = '641: Error creating user account',
_700 = '700: Failed to read from local/session storage',
_701 = '701: Failed to write to local/session storage',
diff --git a/src/services/siwe/index.ts b/src/services/siwe/index.ts
index 682e79c1bc..cc051b6606 100644
--- a/src/services/siwe/index.ts
+++ b/src/services/siwe/index.ts
@@ -5,7 +5,7 @@ import type { BrowserProvider } from 'ethers'
* Prompt the user to sign in with their wallet and set an access_token cookie
* @param provider
*/
-async function signInWithEthereum(provider: BrowserProvider) {
+export const signInWithEthereum = async (provider: BrowserProvider) => {
const { nonce } = await getAuthNonce()
const [network, signer] = await Promise.all([provider.getNetwork(), provider.getSigner()])
@@ -14,7 +14,8 @@ async function signInWithEthereum(provider: BrowserProvider) {
domain: window.location.host,
address: signer.address as `0x${string}`,
// Results in special signing window in MetaMask
- statement: 'Sign in with Ethereum to the app.',
+ statement:
+ 'By signing, you are agreeing to store this data on the Safe Cloud. This does not initiate a transaction or cost any fees.',
uri: window.location.origin,
version: '1',
chainId: Number(network.chainId),
@@ -37,5 +38,3 @@ Issued At: ${message.issuedAt.toISOString()}`
return verifyAuth({ message: signableMessage, signature })
}
-
-export default signInWithEthereum
From 32bccca7b80305b5e42d2f01b9ec38aff36daa4b Mon Sep 17 00:00:00 2001
From: Manuel Gellfart
Date: Wed, 14 Aug 2024 10:30:08 +0200
Subject: [PATCH 03/81] fix: safe creation for chains without 1.4.1 deployed
(#4067)
---
src/components/new-safe/create/AdvancedCreateSafe.tsx | 7 ++++---
src/components/new-safe/create/index.tsx | 7 +++++--
src/components/new-safe/create/steps/StatusStep/index.tsx | 5 ++---
src/utils/chains.ts | 3 ++-
4 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/components/new-safe/create/AdvancedCreateSafe.tsx b/src/components/new-safe/create/AdvancedCreateSafe.tsx
index 631209df72..3c434e3bfd 100644
--- a/src/components/new-safe/create/AdvancedCreateSafe.tsx
+++ b/src/components/new-safe/create/AdvancedCreateSafe.tsx
@@ -14,14 +14,15 @@ import { CREATE_SAFE_CATEGORY } from '@/services/analytics'
import type { CreateSafeInfoItem } from '@/components/new-safe/create/CreateSafeInfos'
import CreateSafeInfos from '@/components/new-safe/create/CreateSafeInfos'
import { useState } from 'react'
-import { LATEST_SAFE_VERSION } from '@/config/constants'
import { type NewSafeFormData } from '.'
-import { type SafeVersion } from '@safe-global/safe-core-sdk-types'
import AdvancedOptionsStep from './steps/AdvancedOptionsStep'
+import { getLatestSafeVersion } from '@/utils/chains'
+import { useCurrentChain } from '@/hooks/useChains'
const AdvancedCreateSafe = () => {
const router = useRouter()
const wallet = useWallet()
+ const chain = useCurrentChain()
const [safeName, setSafeName] = useState('')
const [dynamicHint, setDynamicHint] = useState()
@@ -86,7 +87,7 @@ const AdvancedCreateSafe = () => {
owners: [],
threshold: 1,
saltNonce: 0,
- safeVersion: LATEST_SAFE_VERSION as SafeVersion,
+ safeVersion: getLatestSafeVersion(chain),
}
const onClose = () => {
diff --git a/src/components/new-safe/create/index.tsx b/src/components/new-safe/create/index.tsx
index f82516b23d..7683691eb1 100644
--- a/src/components/new-safe/create/index.tsx
+++ b/src/components/new-safe/create/index.tsx
@@ -17,8 +17,10 @@ import type { CreateSafeInfoItem } from '@/components/new-safe/create/CreateSafe
import CreateSafeInfos from '@/components/new-safe/create/CreateSafeInfos'
import { type ReactElement, useMemo, useState } from 'react'
import ExternalLink from '@/components/common/ExternalLink'
-import { HelpCenterArticle, LATEST_SAFE_VERSION } from '@/config/constants'
+import { HelpCenterArticle } from '@/config/constants'
import { type SafeVersion } from '@safe-global/safe-core-sdk-types'
+import { getLatestSafeVersion } from '@/utils/chains'
+import { useCurrentChain } from '@/hooks/useChains'
export type NewSafeFormData = {
name: string
@@ -99,6 +101,7 @@ const staticHints: Record<
const CreateSafe = () => {
const router = useRouter()
const wallet = useWallet()
+ const chain = useCurrentChain()
const [safeName, setSafeName] = useState('')
const [dynamicHint, setDynamicHint] = useState()
@@ -158,7 +161,7 @@ const CreateSafe = () => {
owners: [],
threshold: 1,
saltNonce: Date.now(),
- safeVersion: LATEST_SAFE_VERSION as SafeVersion,
+ safeVersion: getLatestSafeVersion(chain) as SafeVersion,
}
const onClose = () => {
diff --git a/src/components/new-safe/create/steps/StatusStep/index.tsx b/src/components/new-safe/create/steps/StatusStep/index.tsx
index 47ae72545d..d7c218136c 100644
--- a/src/components/new-safe/create/steps/StatusStep/index.tsx
+++ b/src/components/new-safe/create/steps/StatusStep/index.tsx
@@ -17,8 +17,7 @@ import { Alert, AlertTitle, Box, Button, Paper, Stack, SvgIcon, Typography } fro
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useEffect, useState } from 'react'
-import { LATEST_SAFE_VERSION } from '@/config/constants'
-import { type SafeVersion } from '@safe-global/safe-core-sdk-types'
+import { getLatestSafeVersion } from '@/utils/chains'
const SPEED_UP_THRESHOLD_IN_SECONDS = 15
@@ -85,7 +84,7 @@ export const CreateSafeStatus = ({
threshold: pendingSafe.props.safeAccountConfig.threshold,
saltNonce: Number(pendingSafe.props.safeDeploymentConfig?.saltNonce),
safeAddress,
- safeVersion: pendingSafe.props.safeDeploymentConfig?.safeVersion ?? (LATEST_SAFE_VERSION as SafeVersion),
+ safeVersion: pendingSafe.props.safeDeploymentConfig?.safeVersion ?? getLatestSafeVersion(chain),
})
}
diff --git a/src/utils/chains.ts b/src/utils/chains.ts
index 40cce412cc..4d3940839e 100644
--- a/src/utils/chains.ts
+++ b/src/utils/chains.ts
@@ -4,6 +4,7 @@ import { getExplorerLink } from './gateway'
import { type SafeVersion } from '@safe-global/safe-core-sdk-types'
import { getSafeSingletonDeployment } from '@safe-global/safe-deployments'
import semverSatisfies from 'semver/functions/satisfies'
+import { LATEST_SAFE_VERSION } from '@/config/constants'
/** This version is used if a network does not have the LATEST_SAFE_VERSION deployed yet */
const FALLBACK_SAFE_VERSION = '1.3.0' as const
@@ -62,7 +63,7 @@ export const isRouteEnabled = (route: string, chain?: ChainInfo) => {
}
export const getLatestSafeVersion = (chain: ChainInfo | undefined): SafeVersion => {
- const latestSafeVersion = chain && hasFeature(chain, FEATURES.SAFE_141) ? '1.4.1' : '1.3.0'
+ const latestSafeVersion = chain && hasFeature(chain, FEATURES.SAFE_141) ? LATEST_SAFE_VERSION : FALLBACK_SAFE_VERSION
// Without version filter it will always return the LATEST_SAFE_VERSION constant to avoid automatically updating to the newest version if the deployments change
const latestDeploymentVersion = (getSafeSingletonDeployment({ network: chain?.chainId, released: true })?.version ??
FALLBACK_SAFE_VERSION) as SafeVersion
From 68890bbebbb9dc7f7e78c3552707601dcb20b978 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Wed, 14 Aug 2024 18:40:33 +0200
Subject: [PATCH 04/81] Fix: native transfer only if value > 0 (#4070)
* Fix: native transfer only if value > 0
* Hide Advanced details and Tx checks for Rejection txs
---
.../tx-flow/flows/RejectTx/RejectTx.tsx | 2 +-
src/components/tx/DecodedTx/index.tsx | 2 +-
src/components/tx/SignOrExecuteForm/index.tsx | 32 ++++++++++---------
3 files changed, 19 insertions(+), 17 deletions(-)
diff --git a/src/components/tx-flow/flows/RejectTx/RejectTx.tsx b/src/components/tx-flow/flows/RejectTx/RejectTx.tsx
index 654e461562..5e47cc5b50 100644
--- a/src/components/tx-flow/flows/RejectTx/RejectTx.tsx
+++ b/src/components/tx-flow/flows/RejectTx/RejectTx.tsx
@@ -19,7 +19,7 @@ const RejectTx = ({ txNonce }: RejectTxProps): ReactElement => {
}, [txNonce, setNonce, setSafeTx, setSafeTxError])
return (
-
+
To reject the transaction, a separate rejection transaction will be created to replace the original one.
diff --git a/src/components/tx/DecodedTx/index.tsx b/src/components/tx/DecodedTx/index.tsx
index d6c2d96429..a68c7b615a 100644
--- a/src/components/tx/DecodedTx/index.tsx
+++ b/src/components/tx/DecodedTx/index.tsx
@@ -87,7 +87,7 @@ const DecodedTx = ({
{isMethodCallInAdvanced && decodedData?.method}
- {!showMethodCall && !decodedData?.method && tx?.data.value && 'native transfer'}
+ {!showMethodCall && !decodedData?.method && Number(tx?.data.value) > 0 && 'native transfer'}
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index 326da17b40..e7326adcd5 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -146,24 +146,26 @@ export const SignOrExecuteForm = ({
)}
- Error parsing data}>
- {isApproval && }
-
- {showTxDetails && }
-
-
-
+ {!props.isRejection && (
+ Error parsing data}>
+ {isApproval && }
+
+ {showTxDetails && }
+
+
+
+ )}
- {!isCounterfactualSafe && }
+ {!isCounterfactualSafe && !props.isRejection && }
- {!isCounterfactualSafe && }
+ {!isCounterfactualSafe && !props.isRejection && }
Date: Thu, 15 Aug 2024 08:56:33 +0200
Subject: [PATCH 05/81] 1.41.0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index c4f827b05a..eb7ab76006 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.40.1",
+ "version": "1.41.0",
"type": "module",
"scripts": {
"dev": "next dev",
From 1d7a1400ce9bbb5b14497038bb064a7c0b5c8dac Mon Sep 17 00:00:00 2001
From: Manuel Gellfart
Date: Thu, 15 Aug 2024 10:44:03 +0200
Subject: [PATCH 06/81] fix: update latest Safe version when switching chains
during Safe creation (#4071)
---
.../create/steps/SetNameStep/index.tsx | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/src/components/new-safe/create/steps/SetNameStep/index.tsx b/src/components/new-safe/create/steps/SetNameStep/index.tsx
index c71d1e7ca2..a831ac4d2a 100644
--- a/src/components/new-safe/create/steps/SetNameStep/index.tsx
+++ b/src/components/new-safe/create/steps/SetNameStep/index.tsx
@@ -17,13 +17,19 @@ import MUILink from '@mui/material/Link'
import Link from 'next/link'
import { useRouter } from 'next/router'
import NoWalletConnectedWarning from '../../NoWalletConnectedWarning'
+import { type SafeVersion } from '@safe-global/safe-core-sdk-types'
+import { useCurrentChain } from '@/hooks/useChains'
+import { useEffect } from 'react'
+import { getLatestSafeVersion } from '@/utils/chains'
type SetNameStepForm = {
name: string
+ safeVersion: SafeVersion
}
enum SetNameStepFields {
name = 'name',
+ safeVersion = 'safeVersion',
}
const SET_NAME_STEP_FORM_ID = 'create-safe-set-name-step-form'
@@ -31,22 +37,22 @@ const SET_NAME_STEP_FORM_ID = 'create-safe-set-name-step-form'
function SetNameStep({
data,
onSubmit,
- setStep,
setSafeName,
}: StepRenderProps & { setSafeName: (name: string) => void }) {
const router = useRouter()
const fallbackName = useMnemonicSafeName()
const isWrongChain = useIsWrongChain()
+ const chain = useCurrentChain()
+
const formMethods = useForm({
mode: 'all',
- defaultValues: {
- [SetNameStepFields.name]: data.name,
- },
+ defaultValues: data,
})
const {
handleSubmit,
+ setValue,
formState: { errors, isValid },
} = formMethods
@@ -65,6 +71,11 @@ function SetNameStep({
router.push(AppRoutes.welcome.index)
}
+ // whenever the chain switches we need to update the latest Safe version
+ useEffect(() => {
+ setValue(SetNameStepFields.safeVersion, getLatestSafeVersion(chain))
+ }, [chain, setValue])
+
const isDisabled = isWrongChain || !isValid
return (
From 270051cf18acd470b7a0bcaae6589709a902032d Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Thu, 15 Aug 2024 11:10:54 +0200
Subject: [PATCH 07/81] Fix: ellipsis for Safe names (#4072)
---
src/components/welcome/MyAccounts/AccountItem.tsx | 2 +-
src/components/welcome/MyAccounts/styles.module.css | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/components/welcome/MyAccounts/AccountItem.tsx b/src/components/welcome/MyAccounts/AccountItem.tsx
index bbdd383776..cd162f0d65 100644
--- a/src/components/welcome/MyAccounts/AccountItem.tsx
+++ b/src/components/welcome/MyAccounts/AccountItem.tsx
@@ -81,7 +81,7 @@ const AccountItem = ({ onLinkClick, safeItem, safeOverview }: AccountItemProps)
{name && (
-
+
{name}
)}
diff --git a/src/components/welcome/MyAccounts/styles.module.css b/src/components/welcome/MyAccounts/styles.module.css
index bce1359936..4b97a15341 100644
--- a/src/components/welcome/MyAccounts/styles.module.css
+++ b/src/components/welcome/MyAccounts/styles.module.css
@@ -79,6 +79,7 @@
}
}
+.safeName,
.safeAddress {
white-space: nowrap;
overflow: hidden;
From 3cef4b114436ff93b4d313b3dab8394d10dfbac7 Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Thu, 15 Aug 2024 11:11:25 +0200
Subject: [PATCH 08/81] 1.41.1
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index eb7ab76006..0fc8db4b07 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.41.0",
+ "version": "1.41.1",
"type": "module",
"scripts": {
"dev": "next dev",
From 45f140896aaac7860b8ba82f1de8f9766d702d65 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Fri, 16 Aug 2024 07:45:24 +0200
Subject: [PATCH 09/81] Refactor: plain img tag for safe app icons (#4028)
* Refactor: crossOrigin=anonymous for safe app icons
* Rm crossorigin
* Restore isSafeSrc
* Fallback for external hosts
* Always add crossOrigin="anonymous"
* Rm crossorigin
---
.../safe-apps/SafeAppIconCard/index.test.ts | 14 -----
.../safe-apps/SafeAppIconCard/index.test.tsx | 18 +++++++
.../safe-apps/SafeAppIconCard/index.tsx | 53 +------------------
src/config/securityHeaders.ts | 6 +--
4 files changed, 23 insertions(+), 68 deletions(-)
delete mode 100644 src/components/safe-apps/SafeAppIconCard/index.test.ts
create mode 100644 src/components/safe-apps/SafeAppIconCard/index.test.tsx
diff --git a/src/components/safe-apps/SafeAppIconCard/index.test.ts b/src/components/safe-apps/SafeAppIconCard/index.test.ts
deleted file mode 100644
index 8ac514a8b0..0000000000
--- a/src/components/safe-apps/SafeAppIconCard/index.test.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { _isSafeSrc } from '.'
-
-describe('SafeAppIconCard', () => {
- it('should detect unsafe src', () => {
- expect(_isSafeSrc('https://google.com/test.jpg')).toBe(false)
- expect(_isSafeSrc('data:image/png;base64,')).toBe(false)
- })
-
- it('should detect safe src', () => {
- expect(_isSafeSrc('https://safe-transaction-assets.safe.global/contracts/logos/0x34CfAC646f3.png')).toBe(true)
- expect(_isSafeSrc('https://safe-transaction-assets.staging.5afe.dev/contracts/logos/0x34CfAC.png')).toBe(true)
- expect(_isSafeSrc('/images/transactions/incoming.svg')).toBe(true)
- })
-})
diff --git a/src/components/safe-apps/SafeAppIconCard/index.test.tsx b/src/components/safe-apps/SafeAppIconCard/index.test.tsx
new file mode 100644
index 0000000000..5997c6f67c
--- /dev/null
+++ b/src/components/safe-apps/SafeAppIconCard/index.test.tsx
@@ -0,0 +1,18 @@
+import { render } from '@/tests/test-utils'
+import SafeAppIconCard from '.'
+
+describe('SafeAppIconCard', () => {
+ it('should render an icon', () => {
+ const src = 'https://safe-transaction-assets.safe.global/safe_apps/160/icon.png'
+ const { queryByAltText } = render(
+ ,
+ )
+
+ const img = queryByAltText('test')
+ expect(img).toBeInTheDocument()
+ expect(img).toHaveAttribute('src', src)
+ expect(img).toHaveAttribute('height', '100')
+ expect(img).toHaveAttribute('width', '100')
+ expect(img).not.toHaveAttribute('crossorigin')
+ })
+})
diff --git a/src/components/safe-apps/SafeAppIconCard/index.tsx b/src/components/safe-apps/SafeAppIconCard/index.tsx
index b0333aa342..32b398fff8 100644
--- a/src/components/safe-apps/SafeAppIconCard/index.tsx
+++ b/src/components/safe-apps/SafeAppIconCard/index.tsx
@@ -1,38 +1,7 @@
import ImageFallback from '@/components/common/ImageFallback'
-import { type ReactElement, memo } from 'react'
const APP_LOGO_FALLBACK_IMAGE = `/images/apps/app-placeholder.svg`
-const getIframeContent = (url: string, width: number, height: number, fallback: string): string => {
- return `
-
-
-
-
- `
-}
-
-export const _isSafeSrc = (src: string) => {
- const allowedHosts = ['.safe.global', '.5afe.dev']
- const isRelative = src.startsWith('/')
-
- let hostname = ''
- if (!isRelative) {
- try {
- hostname = new URL(src).hostname
- } catch (e) {
- return false
- }
- }
-
- return isRelative || allowedHosts.some((host) => hostname.endsWith(host))
-}
-
const SafeAppIconCard = ({
src,
alt,
@@ -45,24 +14,6 @@ const SafeAppIconCard = ({
width?: number
height?: number
fallback?: string
-}): ReactElement => {
- if (_isSafeSrc(src)) {
- return
- }
-
- return (
-
- )
-}
+}) =>
-export default memo(SafeAppIconCard)
+export default SafeAppIconCard
diff --git a/src/config/securityHeaders.ts b/src/config/securityHeaders.ts
index 8d3faa3bb1..a0870c5c09 100644
--- a/src/config/securityHeaders.ts
+++ b/src/config/securityHeaders.ts
@@ -13,11 +13,11 @@ export const ContentSecurityPolicy = `
default-src 'self';
connect-src 'self' *;
script-src 'self' https://www.google-analytics.com https://ssl.google-analytics.com 'unsafe-inline' https://*.getbeamer.com https://www.googletagmanager.com https://*.ingest.sentry.io https://sentry.io ${
- !IS_PRODUCTION || /* TODO: remove after moving cypress to görli and testing in staging again!! */ CYPRESS_MNEMONIC
- ? "'unsafe-eval'"
+ !IS_PRODUCTION || CYPRESS_MNEMONIC
+ ? "'unsafe-eval'" // Dev server and cypress need unsafe-eval
: "'wasm-unsafe-eval'"
};
- frame-src *;
+ frame-src http://* https://*;
style-src 'self' 'unsafe-inline' https://*.getbeamer.com https://*.googleapis.com;
font-src 'self' data:;
worker-src 'self' blob:;
From ec57a1d8807e7f62461d6f34e0151dd5bc710a55 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Mon, 19 Aug 2024 10:22:45 +0200
Subject: [PATCH 10/81] Tests: fix create_safe_simple (#4074)
---
cypress/support/utils/wallet.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/cypress/support/utils/wallet.js b/cypress/support/utils/wallet.js
index a9ea82fd88..8daee1aa2d 100644
--- a/cypress/support/utils/wallet.js
+++ b/cypress/support/utils/wallet.js
@@ -32,6 +32,7 @@ export function connectSigner(signer) {
function enterPrivateKey() {
cy.wait(1000)
cy.get(connectWalletBtn)
+ .eq(0)
.should('be.enabled')
.and('be.visible')
.click()
From bc6fd285c6c0685c3f94a97a28d15d7895ce860c Mon Sep 17 00:00:00 2001
From: yuzuswapteam002
Date: Mon, 19 Aug 2024 10:47:46 +0200
Subject: [PATCH 11/81] Tests: add a test for getPeriod (#4040)
---
src/utils/__tests__/date.test.ts | 29 ++++++++++++++++++++++++++++-
1 file changed, 28 insertions(+), 1 deletion(-)
diff --git a/src/utils/__tests__/date.test.ts b/src/utils/__tests__/date.test.ts
index 71213cfee9..26a4b8745e 100644
--- a/src/utils/__tests__/date.test.ts
+++ b/src/utils/__tests__/date.test.ts
@@ -1,4 +1,4 @@
-import { getCountdown } from '../date'
+import { getCountdown, getPeriod } from '../date'
describe('getCountdown', () => {
it('should convert 0 seconds to 0 days, 0 hours, and 0 minutes', () => {
@@ -21,3 +21,30 @@ describe('getCountdown', () => {
expect(result).toEqual({ days: 1, hours: 10, minutes: 17 })
})
})
+
+describe('getPeriod', () => {
+ it('returns correct period for days', () => {
+ expect(getPeriod(86400)).toBe('1 day')
+ expect(getPeriod(172800)).toBe('2 days')
+ })
+
+ it('returns correct period for hours', () => {
+ expect(getPeriod(3600)).toBe('1 hour')
+ expect(getPeriod(7200)).toBe('2 hours')
+ })
+
+ it('returns correct period for minutes', () => {
+ expect(getPeriod(60)).toBe('1 minute')
+ expect(getPeriod(120)).toBe('2 minutes')
+ })
+
+ it('returns undefined for seconds less than 60', () => {
+ expect(getPeriod(59)).toBeUndefined()
+ })
+
+ it('returns correct period when there are multiple units', () => {
+ expect(getPeriod(90000)).toBe('1 day')
+ expect(getPeriod(86400 + 3600)).toBe('1 day')
+ expect(getPeriod(86400 + 3600 + 60)).toBe('1 day')
+ })
+})
From 241604d081ae18c07f8b5d03c4601ce835413a27 Mon Sep 17 00:00:00 2001
From: Manuel Gellfart
Date: Mon, 19 Aug 2024 10:50:30 +0200
Subject: [PATCH 12/81] feat: upgrade zodiac to enable recovery on Base (#4062)
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index 0fc8db4b07..d640492d91 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
"@emotion/react": "^11.11.0",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0",
- "@gnosis.pm/zodiac": "^4.0.1",
+ "@gnosis.pm/zodiac": "^4.0.3",
"@mui/icons-material": "^5.14.20",
"@mui/material": "^5.14.20",
"@mui/x-date-pickers": "^5.0.20",
diff --git a/yarn.lock b/yarn.lock
index b77fb142d6..20a45822ae 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2902,10 +2902,10 @@
resolved "https://registry.yarnpkg.com/@gnosis.pm/safe-contracts/-/safe-contracts-1.3.0.tgz#316741a7690d8751a1f701538cfc9ec80866eedc"
integrity sha512-1p+1HwGvxGUVzVkFjNzglwHrLNA67U/axP0Ct85FzzH8yhGJb4t9jDjPYocVMzLorDoWAfKicGy1akPY9jXRVw==
-"@gnosis.pm/zodiac@^4.0.1":
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/@gnosis.pm/zodiac/-/zodiac-4.0.1.tgz#a117d972b8cc361d097246fff0815c1badca3990"
- integrity sha512-zq8PSr3uNmMjlZxmG3Rq9V5dHINeeyAe7smNMD+m0UlRGjrcffT29gg9pLyV6RNYR+8VpG7ehv4AJZ02DccscQ==
+"@gnosis.pm/zodiac@^4.0.3":
+ version "4.0.3"
+ resolved "https://registry.yarnpkg.com/@gnosis.pm/zodiac/-/zodiac-4.0.3.tgz#3323f496cda279e2a68ca2bf726ad840388e8229"
+ integrity sha512-yliHytBRlb4wNkeiYsaaAvYZC5VwiUBVfJ+HLEmjnWPG2EHB5tvAOUboDU7XvSQ4GUJAz8h2YUrph0XkH+/xfA==
dependencies:
"@gnosis.pm/mock-contract" "^4.0.0"
"@gnosis.pm/safe-contracts" "1.3.0"
From 7c7d8631d2743591ab0744ed0a0517e6916d1020 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Tue, 20 Aug 2024 07:28:36 +0200
Subject: [PATCH 13/81] Analytics: ecosystem id in safe creation params (#4073)
* Analytics: ecosystem id in safe creation params
* Add env var to the build
* Check Status -> Check status on block explorer
* CF creation
---
.github/workflows/build/action.yml | 1 +
src/components/new-safe/create/logic/index.ts | 30 +++++++++++++------
.../create/steps/ReviewStep/index.tsx | 5 ++--
.../create/steps/StatusStep/StatusMessage.tsx | 4 ++-
.../tx/ExecutionMethodSelector/index.tsx | 2 +-
src/config/constants.ts | 3 ++
6 files changed, 31 insertions(+), 14 deletions(-)
diff --git a/.github/workflows/build/action.yml b/.github/workflows/build/action.yml
index fd3d7998f2..6b8ef9d45e 100644
--- a/.github/workflows/build/action.yml
+++ b/.github/workflows/build/action.yml
@@ -59,3 +59,4 @@ runs:
NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION }}
NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING }}
NEXT_PUBLIC_SPINDL_SDK_KEY: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SPINDL_SDK_KEY }}
+ NEXT_PUBLIC_ECOSYSTEM_ID_ADDRESS: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_ECOSYSTEM_ID_ADDRESS }}
diff --git a/src/components/new-safe/create/logic/index.ts b/src/components/new-safe/create/logic/index.ts
index 875be495fe..1be9d299bd 100644
--- a/src/components/new-safe/create/logic/index.ts
+++ b/src/components/new-safe/create/logic/index.ts
@@ -18,6 +18,7 @@ import { isValidSafeVersion } from '@/hooks/coreSDK/safeCoreSDK'
import { backOff } from 'exponential-backoff'
import { EMPTY_DATA, ZERO_ADDRESS } from '@safe-global/protocol-kit/dist/src/utils/constants'
import { getLatestSafeVersion } from '@/utils/chains'
+import { ECOSYSTEM_ID_ADDRESS } from '@/config/constants'
export type SafeCreationProps = {
owners: string[]
@@ -82,16 +83,27 @@ export const encodeSafeCreationTx = async ({
const readOnlyProxyContract = await getReadOnlyProxyFactoryContract(usedSafeVersion)
const readOnlyFallbackHandlerContract = await getReadOnlyFallbackHandlerContract(usedSafeVersion)
- // @ts-ignore union type is too complex
- const setupData = readOnlySafeContract.encode('setup', [
+ const callData = {
owners,
threshold,
- ZERO_ADDRESS,
- EMPTY_DATA,
- await readOnlyFallbackHandlerContract.getAddress(),
- ZERO_ADDRESS,
- '0',
- ZERO_ADDRESS,
+ to: ZERO_ADDRESS,
+ data: EMPTY_DATA,
+ fallbackHandler: await readOnlyFallbackHandlerContract.getAddress(),
+ paymentToken: ZERO_ADDRESS,
+ payment: 0,
+ paymentReceiver: ECOSYSTEM_ID_ADDRESS,
+ }
+
+ // @ts-ignore union type is too complex
+ const setupData = readOnlySafeContract.encode('setup', [
+ callData.owners,
+ callData.threshold,
+ callData.to,
+ callData.data,
+ callData.fallbackHandler,
+ callData.paymentToken,
+ callData.payment,
+ callData.paymentReceiver,
])
return readOnlyProxyContract.encode('createProxyWithNonce', [
@@ -191,7 +203,7 @@ export const relaySafeCreation = async (
fallbackHandler: fallbackHandlerAddress,
paymentToken: ZERO_ADDRESS,
payment: 0,
- paymentReceiver: ZERO_ADDRESS,
+ paymentReceiver: ECOSYSTEM_ID_ADDRESS,
}
// @ts-ignore
diff --git a/src/components/new-safe/create/steps/ReviewStep/index.tsx b/src/components/new-safe/create/steps/ReviewStep/index.tsx
index a161b3ef0b..846813120d 100644
--- a/src/components/new-safe/create/steps/ReviewStep/index.tsx
+++ b/src/components/new-safe/create/steps/ReviewStep/index.tsx
@@ -38,7 +38,7 @@ import { type ChainInfo } from '@safe-global/safe-gateway-typescript-sdk'
import classnames from 'classnames'
import { useRouter } from 'next/router'
import { useMemo, useState } from 'react'
-import { getLatestSafeVersion } from '@/utils/chains'
+import { ECOSYSTEM_ID_ADDRESS } from '@/config/constants'
export const NetworkFee = ({
totalFee,
@@ -130,8 +130,6 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps {
return {
owners: data.owners.map((owner) => owner.address),
@@ -169,6 +167,7 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps owner.address),
fallbackHandler: await readOnlyFallbackHandlerContract.getAddress(),
+ paymentReceiver: ECOSYSTEM_ID_ADDRESS,
},
}
diff --git a/src/components/new-safe/create/steps/StatusStep/StatusMessage.tsx b/src/components/new-safe/create/steps/StatusStep/StatusMessage.tsx
index 3776d953f7..fc0b04589a 100644
--- a/src/components/new-safe/create/steps/StatusStep/StatusMessage.tsx
+++ b/src/components/new-safe/create/steps/StatusStep/StatusMessage.tsx
@@ -72,7 +72,9 @@ const StatusMessage = ({
{stepInfo.instruction}
)}
- {!isError && explorerLink && Check Status }
+ {!isError && explorerLink && (
+ Check status on block explorer
+ )}
>
)
diff --git a/src/components/tx/ExecutionMethodSelector/index.tsx b/src/components/tx/ExecutionMethodSelector/index.tsx
index da3c52f0e2..645829ed13 100644
--- a/src/components/tx/ExecutionMethodSelector/index.tsx
+++ b/src/components/tx/ExecutionMethodSelector/index.tsx
@@ -56,7 +56,7 @@ const _ExecutionMethodSelector = ({
sx={{ flex: 1 }}
value={ExecutionMethod.RELAY}
label={
-
+
Sponsored by
diff --git a/src/config/constants.ts b/src/config/constants.ts
index f31a12033a..b8a20080f1 100644
--- a/src/config/constants.ts
+++ b/src/config/constants.ts
@@ -107,3 +107,6 @@ export const REDEFINE_API = process.env.NEXT_PUBLIC_REDEFINE_API
export const REDEFINE_ARTICLE = 'https://safe.mirror.xyz/rInLWZwD_sf7enjoFerj6FIzCYmVMGrrV8Nhg4THdwI'
export const CHAINALYSIS_OFAC_CONTRACT = '0x40c57923924b5c5c5455c48d93317139addac8fb'
+
+export const ECOSYSTEM_ID_ADDRESS =
+ process.env.NEXT_PUBLIC_ECOSYSTEM_ID_ADDRESS || '0x0000000000000000000000000000000000000000'
From ad9172b827861ee89fdbd51971d6df7113a99644 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Tue, 20 Aug 2024 16:45:05 +0200
Subject: [PATCH 14/81] Analytics: restore safe address in the safe_created
event (#4077)
* Analytics: restore safe address in the safe_created event
* Temp: comment out storybook build
---
.github/workflows/deploy-dev.yml | 2 +-
package.json | 2 +-
src/features/counterfactual/hooks/usePendingSafeStatuses.ts | 3 +++
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml
index a56a220e14..aa64e261a4 100644
--- a/.github/workflows/deploy-dev.yml
+++ b/.github/workflows/deploy-dev.yml
@@ -43,7 +43,7 @@ jobs:
secrets: ${{ toJSON(secrets) }}
if: startsWith(github.ref, 'refs/heads/main')
- - uses: ./.github/workflows/build-storybook
+ #- uses: ./.github/workflows/build-storybook
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v3
diff --git a/package.json b/package.json
index d640492d91..b7b116cce1 100644
--- a/package.json
+++ b/package.json
@@ -31,7 +31,7 @@
"update-wc": "yarn add @walletconnect/web3wallet@latest @walletconnect/utils@latest; yarn add -D @walletconnect/types@latest",
"prepare": "husky",
"storybook": "storybook dev -p 6006",
- "build-storybook": "storybook build"
+ "build-storybook": "storybook build --quiet"
},
"engines": {
"node": ">=16"
diff --git a/src/features/counterfactual/hooks/usePendingSafeStatuses.ts b/src/features/counterfactual/hooks/usePendingSafeStatuses.ts
index 566911da6e..296765c48f 100644
--- a/src/features/counterfactual/hooks/usePendingSafeStatuses.ts
+++ b/src/features/counterfactual/hooks/usePendingSafeStatuses.ts
@@ -19,6 +19,7 @@ import { CREATE_SAFE_EVENTS, trackEvent } from '@/services/analytics'
import { useAppDispatch, useAppSelector } from '@/store'
import { useEffect, useRef } from 'react'
import { isSmartContract } from '@/utils/wallets'
+import { gtmSetSafeAddress } from '@/services/analytics/gtm'
export const safeCreationPendingStatuses: Partial> = {
[SafeCreationEvent.PROCESSING]: PendingSafeStatus.PROCESSING,
@@ -109,6 +110,8 @@ const usePendingSafeStatus = (): void => {
const unsubFns = Object.entries(safeCreationPendingStatuses).map(([event, status]) =>
safeCreationSubscribe(event as SafeCreationEvent, async (detail) => {
if (event === SafeCreationEvent.SUCCESS) {
+ gtmSetSafeAddress(detail.safeAddress)
+
// TODO: Possible to add a label with_tx, without_tx?
trackEvent(CREATE_SAFE_EVENTS.ACTIVATED_SAFE)
From 95f4fbb902ec2786b2eabf4a3d84ee13559c2338 Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Tue, 20 Aug 2024 17:03:48 +0200
Subject: [PATCH 15/81] 1.41.2
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index b7b116cce1..ef8930c3b1 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.41.1",
+ "version": "1.41.2",
"type": "module",
"scripts": {
"dev": "next dev",
From 5cf00d38a1dd329a45294d1d1f3f3900f4f3fe1f Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Wed, 21 Aug 2024 10:22:52 +0200
Subject: [PATCH 16/81] Tests: skip a failing case in tx-builder tests
---
cypress/e2e/safe-apps/tx-builder.spec.cy.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cypress/e2e/safe-apps/tx-builder.spec.cy.js b/cypress/e2e/safe-apps/tx-builder.spec.cy.js
index a947418747..3f4ae3822e 100644
--- a/cypress/e2e/safe-apps/tx-builder.spec.cy.js
+++ b/cypress/e2e/safe-apps/tx-builder.spec.cy.js
@@ -100,7 +100,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
cy.findByText(safeapps.thresholdStr2).should('exist')
})
- it('Verify a batch can be created from an ABI', () => {
+ it.skip('Verify a batch can be created from an ABI', () => {
cy.enter(iframeSelector).then((getBody) => {
getBody().findByLabelText(safeapps.enterABIStr).type(safeapps.abi)
getBody().findByLabelText(safeapps.toAddressStr).type(safeAppSafes.SEP_SAFEAPP_SAFE_2)
From f89577485c155ec4a167d22e2212dc72ae9b5c41 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Thu, 22 Aug 2024 13:06:42 +0200
Subject: [PATCH 17/81] Chore(deps): Bump the npm_and_yarn group with 7 updates
(#4084)
Bumps the npm_and_yarn group with 7 updates:
| Package | From | To |
| --- | --- | --- |
| [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) | `4.9.3` | `4.9.6` |
| [@openzeppelin/contracts-upgradeable](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable) | `5.0.0` | `5.0.2` |
| [@solana/web3.js](https://github.com/solana-labs/solana-web3.js) | `1.87.1` | `1.95.3` |
| [braces](https://github.com/micromatch/braces) | `3.0.2` | `3.0.3` |
| [ejs](https://github.com/mde/ejs) | `3.1.9` | `3.1.10` |
| [es5-ext](https://github.com/medikoo/es5-ext) | `0.10.62` | `0.10.64` |
| [follow-redirects](https://github.com/follow-redirects/follow-redirects) | `1.15.3` | `1.15.6` |
Updates `@openzeppelin/contracts` from 4.9.3 to 4.9.6
- [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases)
- [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md)
- [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v4.9.3...v4.9.6)
Updates `@openzeppelin/contracts-upgradeable` from 5.0.0 to 5.0.2
- [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/releases)
- [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/blob/master/CHANGELOG.md)
- [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable/compare/v5.0.0...v5.0.2)
Updates `@solana/web3.js` from 1.87.1 to 1.95.3
- [Release notes](https://github.com/solana-labs/solana-web3.js/releases)
- [Commits](https://github.com/solana-labs/solana-web3.js/compare/v1.87.1...v1.95.3)
Updates `braces` from 3.0.2 to 3.0.3
- [Changelog](https://github.com/micromatch/braces/blob/master/CHANGELOG.md)
- [Commits](https://github.com/micromatch/braces/compare/3.0.2...3.0.3)
Updates `ejs` from 3.1.9 to 3.1.10
- [Release notes](https://github.com/mde/ejs/releases)
- [Commits](https://github.com/mde/ejs/compare/v3.1.9...v3.1.10)
Updates `es5-ext` from 0.10.62 to 0.10.64
- [Release notes](https://github.com/medikoo/es5-ext/releases)
- [Changelog](https://github.com/medikoo/es5-ext/blob/main/CHANGELOG.md)
- [Commits](https://github.com/medikoo/es5-ext/compare/v0.10.62...v0.10.64)
Updates `follow-redirects` from 1.15.3 to 1.15.6
- [Release notes](https://github.com/follow-redirects/follow-redirects/releases)
- [Commits](https://github.com/follow-redirects/follow-redirects/compare/v1.15.3...v1.15.6)
---
updated-dependencies:
- dependency-name: "@openzeppelin/contracts"
dependency-type: direct:development
dependency-group: npm_and_yarn
- dependency-name: "@openzeppelin/contracts-upgradeable"
dependency-type: indirect
dependency-group: npm_and_yarn
- dependency-name: "@solana/web3.js"
dependency-type: indirect
dependency-group: npm_and_yarn
- dependency-name: braces
dependency-type: indirect
dependency-group: npm_and_yarn
- dependency-name: ejs
dependency-type: indirect
dependency-group: npm_and_yarn
- dependency-name: es5-ext
dependency-type: indirect
dependency-group: npm_and_yarn
- dependency-name: follow-redirects
dependency-type: indirect
dependency-group: npm_and_yarn
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 213 ++++++++++++++++++++++++++++++++++++---------------
2 files changed, 151 insertions(+), 64 deletions(-)
diff --git a/package.json b/package.json
index ef8930c3b1..152c95a91a 100644
--- a/package.json
+++ b/package.json
@@ -99,7 +99,7 @@
"@cowprotocol/app-data": "^2.1.0",
"@faker-js/faker": "^8.1.0",
"@next/bundle-analyzer": "^13.5.6",
- "@openzeppelin/contracts": "^4.9.2",
+ "@openzeppelin/contracts": "^4.9.6",
"@safe-global/safe-core-sdk-types": "^5.0.1",
"@sentry/types": "^7.74.0",
"@storybook/addon-designs": "^8.0.0",
diff --git a/yarn.lock b/yarn.lock
index 20a45822ae..a6e4dbd650 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1104,13 +1104,20 @@
dependencies:
regenerator-runtime "^0.13.11"
-"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.6", "@babel/runtime@^7.17.2", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.21.0", "@babel/runtime@^7.22.6", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
+"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.6", "@babel/runtime@^7.17.8", "@babel/runtime@^7.18.3", "@babel/runtime@^7.18.9", "@babel/runtime@^7.21.0", "@babel/runtime@^7.23.2", "@babel/runtime@^7.23.5", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.4.tgz#de795accd698007a66ba44add6cc86542aff1edd"
integrity sha512-dkxf7+hn8mFBwKjs9bvBlArzLVxVbS8usaPUDd5p2a9JCL9tB8OaOVN1isD4+Xyk4ns89/xeOmbQvgdK7IIVdA==
dependencies:
regenerator-runtime "^0.14.0"
+"@babel/runtime@^7.25.0":
+ version "7.25.0"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.0.tgz#3af9a91c1b739c569d5d80cc917280919c544ecb"
+ integrity sha512-7dRy4DwXwtzBrPbZflqxnvfxLF8kdZXPkhymtDeFoFqE6ldzjQFgYTtYIFARcLEYDrqfBfYcZt1WqFxRoyC9Rw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
"@babel/template@^7.22.15", "@babel/template@^7.24.0", "@babel/template@^7.3.3":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
@@ -3786,19 +3793,31 @@
jsbi "^3.1.5"
sha.js "^2.4.11"
-"@noble/curves@1.2.0", "@noble/curves@^1.2.0", "@noble/curves@~1.2.0":
+"@noble/curves@1.2.0", "@noble/curves@~1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35"
integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==
dependencies:
"@noble/hashes" "1.3.2"
+"@noble/curves@^1.4.2":
+ version "1.5.0"
+ resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.5.0.tgz#7a9b9b507065d516e6dce275a1e31db8d2a100dd"
+ integrity sha512-J5EKamIHnKPyClwVrzmaf5wSdQXgdHcPZIZLu3bwnbeCx8/7NPK5q2ZBWF+5FvYGByjiQQsJYX6jfgB2wDPn3A==
+ dependencies:
+ "@noble/hashes" "1.4.0"
+
"@noble/hashes@1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39"
integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==
-"@noble/hashes@^1.2.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.3.3", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2":
+"@noble/hashes@1.4.0", "@noble/hashes@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426"
+ integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==
+
+"@noble/hashes@^1.2.0", "@noble/hashes@^1.3.3", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.2":
version "1.3.3"
resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699"
integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==
@@ -3825,14 +3844,14 @@
fastq "^1.6.0"
"@openzeppelin/contracts-upgradeable@^5.0.0":
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.0.tgz#859c00c55f04b6dda85b3c88bce507d65019888f"
- integrity sha512-D54RHzkOKHQ8xUssPgQe2d/U92mwaiBDY7qCCVGq6VqwQjsT3KekEQ3bonev+BLP30oZ0R1U6YC8/oLpizgC5Q==
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz#3e5321a2ecdd0b206064356798c21225b6ec7105"
+ integrity sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ==
-"@openzeppelin/contracts@^4.9.2":
- version "4.9.3"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.3.tgz#00d7a8cf35a475b160b3f0293a6403c511099364"
- integrity sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==
+"@openzeppelin/contracts@^4.9.6":
+ version "4.9.6"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677"
+ integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==
"@openzeppelin/contracts@^5.0.0":
version "5.0.0"
@@ -4281,7 +4300,7 @@
dependencies:
"@sinonjs/commons" "^3.0.0"
-"@solana/buffer-layout@^4.0.0":
+"@solana/buffer-layout@^4.0.1":
version "4.0.1"
resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15"
integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA==
@@ -4289,25 +4308,25 @@
buffer "~6.0.3"
"@solana/web3.js@^1.70.1":
- version "1.87.1"
- resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.87.1.tgz#da376cebbc4cc97ece0cb028d799163ea147f299"
- integrity sha512-E8Y9bNlZ8TQlhOvCx1b7jG+TjA4SJLVwufmIk1+tcQctUhK5HiB1Q8ljd4yQDkFlk6OOeAlAeqvW0YntWJU94Q==
- dependencies:
- "@babel/runtime" "^7.22.6"
- "@noble/curves" "^1.2.0"
- "@noble/hashes" "^1.3.1"
- "@solana/buffer-layout" "^4.0.0"
- agentkeepalive "^4.3.0"
+ version "1.95.3"
+ resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.3.tgz#70b5f4d76823f56b5af6403da51125fffeb65ff3"
+ integrity sha512-O6rPUN0w2fkNqx/Z3QJMB9L225Ex10PRDH8bTaIUPZXMPV0QP8ZpPvjQnXK+upUczlRgzHzd6SjKIha1p+I6og==
+ dependencies:
+ "@babel/runtime" "^7.25.0"
+ "@noble/curves" "^1.4.2"
+ "@noble/hashes" "^1.4.0"
+ "@solana/buffer-layout" "^4.0.1"
+ agentkeepalive "^4.5.0"
bigint-buffer "^1.1.5"
bn.js "^5.2.1"
borsh "^0.7.0"
bs58 "^4.0.1"
buffer "6.0.3"
fast-stable-stringify "^1.0.0"
- jayson "^4.1.0"
- node-fetch "^2.6.12"
- rpc-websockets "^7.5.1"
- superstruct "^0.14.2"
+ jayson "^4.1.1"
+ node-fetch "^2.7.0"
+ rpc-websockets "^9.0.2"
+ superstruct "^2.0.2"
"@spindl-xyz/attribution-lite@^1.4.0":
version "1.4.0"
@@ -5319,6 +5338,13 @@
dependencies:
tslib "^2.4.0"
+"@swc/helpers@^0.5.11":
+ version "0.5.12"
+ resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.12.tgz#37aaca95284019eb5d2207101249435659709f4b"
+ integrity sha512-KMZNXiGibsW9kvZAO1Pam2JPTDBm+KSHMMHWdsyI/1DbIZjT2A6Gy3hblVXUMEDvUAKq+e0vL0X0o54owWji7g==
+ dependencies:
+ tslib "^2.4.0"
+
"@testing-library/cypress@^8.0.7":
version "8.0.7"
resolved "https://registry.yarnpkg.com/@testing-library/cypress/-/cypress-8.0.7.tgz#18315eba3cf8852808afadf122e4858406384015"
@@ -6075,6 +6101,11 @@
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
+"@types/uuid@^8.3.4":
+ version "8.3.4"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc"
+ integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==
+
"@types/uuid@^9.0.1":
version "9.0.8"
resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba"
@@ -6097,6 +6128,13 @@
dependencies:
"@types/node" "*"
+"@types/ws@^8.2.2":
+ version "8.5.12"
+ resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.5.12.tgz#619475fe98f35ccca2a2f6c137702d85ec247b7e"
+ integrity sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==
+ dependencies:
+ "@types/node" "*"
+
"@types/yargs-parser@*":
version "21.0.1"
resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.1.tgz#07773d7160494d56aa882d7531aac7319ea67c3b"
@@ -7167,7 +7205,7 @@ agent-base@6, agent-base@^6.0.2:
dependencies:
debug "4"
-agentkeepalive@^4.3.0:
+agentkeepalive@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.5.0.tgz#2673ad1389b3c418c5a20c5d7364f93ca04be923"
integrity sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==
@@ -7958,11 +7996,11 @@ brace-expansion@^2.0.1:
balanced-match "^1.0.0"
braces@^3.0.2, braces@~3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
- integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
+ integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
dependencies:
- fill-range "^7.0.1"
+ fill-range "^7.1.1"
brorand@^1.0.1, brorand@^1.0.5, brorand@^1.1.0:
version "1.1.0"
@@ -9506,9 +9544,9 @@ eip55@^2.1.1:
keccak "^3.0.3"
ejs@^3.1.6, ejs@^3.1.8:
- version "3.1.9"
- resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.9.tgz#03c9e8777fe12686a9effcef22303ca3d8eeb361"
- integrity sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==
+ version "3.1.10"
+ resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b"
+ integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==
dependencies:
jake "^10.8.5"
@@ -9776,13 +9814,14 @@ es-to-primitive@^1.2.1:
is-date-object "^1.0.1"
is-symbol "^1.0.2"
-es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
- version "0.10.62"
- resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.62.tgz#5e6adc19a6da524bf3d1e02bbc8960e5eb49a9a5"
- integrity sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==
+es5-ext@^0.10.35, es5-ext@^0.10.46, es5-ext@^0.10.50, es5-ext@^0.10.53, es5-ext@^0.10.61, es5-ext@^0.10.62, es5-ext@~0.10.14, es5-ext@~0.10.2, es5-ext@~0.10.46:
+ version "0.10.64"
+ resolved "https://registry.yarnpkg.com/es5-ext/-/es5-ext-0.10.64.tgz#12e4ffb48f1ba2ea777f1fcdd1918ef73ea21714"
+ integrity sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==
dependencies:
es6-iterator "^2.0.3"
es6-symbol "^3.1.3"
+ esniff "^2.0.1"
next-tick "^1.1.0"
es6-iterator@^2.0.3:
@@ -10149,6 +10188,16 @@ eslint@^8.57.0:
strip-ansi "^6.0.1"
text-table "^0.2.0"
+esniff@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/esniff/-/esniff-2.0.1.tgz#a4d4b43a5c71c7ec51c51098c1d8a29081f9b308"
+ integrity sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==
+ dependencies:
+ d "^1.0.1"
+ es5-ext "^0.10.62"
+ event-emitter "^0.3.5"
+ type "^2.7.2"
+
espree@^9.6.0, espree@^9.6.1:
version "9.6.1"
resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f"
@@ -10475,6 +10524,11 @@ eventemitter3@^4.0.7:
resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f"
integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==
+eventemitter3@^5.0.1:
+ version "5.0.1"
+ resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4"
+ integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==
+
events@3.3.0, events@^3.2.0, events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
@@ -10788,10 +10842,10 @@ filesize@^10.0.12:
resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.1.tgz#eb98ce885aa73741199748e70e5b7339cc22c5ff"
integrity sha512-L0cdwZrKlwZQkMSFnCflJ6J2Y+5egO/p3vgRSDQGxQt++QbUZe5gMbRO6kg6gzwQDPvq2Fk9AmoxUNfZ5gdqaQ==
-fill-range@^7.0.1:
- version "7.0.1"
- resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
- integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
+fill-range@^7.1.1:
+ version "7.1.1"
+ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
+ integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
dependencies:
to-regex-range "^5.0.1"
@@ -10939,9 +10993,9 @@ flow-parser@0.*:
integrity sha512-E/mv51GYJfLuRX6fZnw4M52gBxYa8pkHUOgNEZOcQK2RTXS8YXeU5rlalkTcY99UpwbeNVCSUFKaavpOksi/pQ==
follow-redirects@^1.14.8, follow-redirects@^1.15.0:
- version "1.15.3"
- resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.3.tgz#fe2f3ef2690afce7e82ed0b44db08165b207123a"
- integrity sha512-1VzOtuEM8pC9SFU1E+8KfTjZyMztRsgEfwQl44z8A25uy13jSzTj6dyK2Df52iV0vgHCfBwLhDWevLn95w5v6Q==
+ version "1.15.6"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
+ integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
for-each@^0.3.3:
version "0.3.3"
@@ -12445,10 +12499,10 @@ jake@^10.8.5:
filelist "^1.0.4"
minimatch "^3.1.2"
-jayson@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.0.tgz#60dc946a85197317f2b1439d672a8b0a99cea2f9"
- integrity sha512-R6JlbyLN53Mjku329XoRT2zJAE6ZgOQ8f91ucYdMCD4nkGCF9kZSrcGXpHIU4jeKj58zUZke2p+cdQchU7Ly7A==
+jayson@^4.1.1:
+ version "4.1.2"
+ resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.1.2.tgz#443c26a8658703e0b2e881117b09395d88b6982e"
+ integrity sha512-5nzMWDHy6f+koZOuYsArh2AXs73NfWYVlFyJJuCedr93GpY+Ku8qq10ropSXVfHK+H0T6paA88ww+/dV+1fBNA==
dependencies:
"@types/connect" "^3.4.33"
"@types/node" "^12.12.54"
@@ -12461,7 +12515,7 @@ jayson@^4.1.0:
isomorphic-ws "^4.0.1"
json-stringify-safe "^5.0.1"
uuid "^8.3.2"
- ws "^7.4.5"
+ ws "^7.5.10"
jest-changed-files@^29.7.0:
version "29.7.0"
@@ -15886,13 +15940,16 @@ rollup@^2.43.1:
optionalDependencies:
fsevents "~2.3.2"
-rpc-websockets@^7.5.1:
- version "7.6.0"
- resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-7.6.0.tgz#d3f4c0dac108ca35566b0e31552c32e58928cd04"
- integrity sha512-Jgcs8q6t8Go98dEulww1x7RysgTkzpCMelVxZW4hvuyFtOGpeUz9prpr2KjUa/usqxgFCd9Tu3+yhHEP9GVmiQ==
+rpc-websockets@^9.0.2:
+ version "9.0.2"
+ resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.0.2.tgz#4c1568d00b8100f997379a363478f41f8f4b242c"
+ integrity sha512-YzggvfItxMY3Lwuax5rC18inhbjJv9Py7JXRHxTIi94JOLrqBsSsUUc5bbl5W6c11tXhdfpDPK0KzBhoGe8jjw==
dependencies:
- "@babel/runtime" "^7.17.2"
- eventemitter3 "^4.0.7"
+ "@swc/helpers" "^0.5.11"
+ "@types/uuid" "^8.3.4"
+ "@types/ws" "^8.2.2"
+ buffer "^6.0.3"
+ eventemitter3 "^5.0.1"
uuid "^8.3.2"
ws "^8.5.0"
optionalDependencies:
@@ -16580,7 +16637,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16668,7 +16734,14 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -16773,16 +16846,16 @@ stylus@^0.59.0:
sax "~1.2.4"
source-map "^0.7.3"
-superstruct@^0.14.2:
- version "0.14.2"
- resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.14.2.tgz#0dbcdf3d83676588828f1cf5ed35cda02f59025b"
- integrity sha512-nPewA6m9mR3d6k7WkZ8N8zpTWfenFH3q9pA2PkuiZxINr9DKB2+40wEQf0ixn8VaGuJ78AB6iWOtStI+/4FKZQ==
-
superstruct@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-1.0.3.tgz#de626a5b49c6641ff4d37da3c7598e7a87697046"
integrity sha512-8iTn3oSS8nRGn+C2pgXSKPI3jmpm6FExNazNpjvqS6ZUJQCej3PUXEKM8NjHBOs54ExM+LPW/FBRhymrdcCiSg==
+superstruct@^2.0.2:
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54"
+ integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A==
+
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -18339,7 +18412,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18357,6 +18430,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
@@ -18393,7 +18475,7 @@ 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.9, ws@^7.2.0, ws@^7.3.1, ws@^7.4.5, ws@^7.5.1:
+ws@7.5.9, ws@^7.2.0, ws@^7.3.1, ws@^7.5.1:
version "7.5.9"
resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.9.tgz#54fa7db29f4c7cec68b1ddd3a89de099942bb591"
integrity sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==
@@ -18408,6 +18490,11 @@ ws@8.5.0:
resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"
integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==
+ws@^7.5.10:
+ version "7.5.10"
+ resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9"
+ integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==
+
ws@^8.11.0, ws@^8.2.3, ws@^8.5.0:
version "8.16.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4"
From 39d4170fb4fa681e7c06012a0315d4c5c848df39 Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Thu, 22 Aug 2024 15:58:28 +0200
Subject: [PATCH 18/81] Fix: tx details - always show method parameters
---
src/components/common/Table/styles.module.css | 4 ++++
.../TxDetails/TxData/DecodedData/MethodDetails/index.tsx | 2 +-
.../transactions/TxDetails/TxData/DecodedData/index.tsx | 4 +---
3 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/components/common/Table/styles.module.css b/src/components/common/Table/styles.module.css
index 9dad10da8c..33e2c2fd97 100644
--- a/src/components/common/Table/styles.module.css
+++ b/src/components/common/Table/styles.module.css
@@ -29,6 +29,10 @@
word-break: break-all;
}
+.title span:nth-child(2) {
+ word-break: normal;
+}
+
.gridRow > * {
flex-shrink: 0;
}
diff --git a/src/components/transactions/TxDetails/TxData/DecodedData/MethodDetails/index.tsx b/src/components/transactions/TxDetails/TxData/DecodedData/MethodDetails/index.tsx
index 989cb942e6..1818c49a51 100644
--- a/src/components/transactions/TxDetails/TxData/DecodedData/MethodDetails/index.tsx
+++ b/src/components/transactions/TxDetails/TxData/DecodedData/MethodDetails/index.tsx
@@ -12,7 +12,7 @@ type MethodDetailsProps = {
}
}
-export const MethodDetails = ({ data, addressInfoIndex }: MethodDetailsProps): ReactElement | null => {
+export const MethodDetails = ({ data, addressInfoIndex }: MethodDetailsProps): ReactElement => {
if (!data.parameters?.length) {
return No parameters
}
diff --git a/src/components/transactions/TxDetails/TxData/DecodedData/index.tsx b/src/components/transactions/TxDetails/TxData/DecodedData/index.tsx
index 5647cd53d1..c8d23ff1dd 100644
--- a/src/components/transactions/TxDetails/TxData/DecodedData/index.tsx
+++ b/src/components/transactions/TxDetails/TxData/DecodedData/index.tsx
@@ -51,9 +51,7 @@ export const DecodedData = ({ txData, toInfo }: Props): ReactElement | null => {
let decodedData = <>>
if (txData.dataDecoded) {
- if (amountInWei === '0') {
- decodedData =
- }
+ decodedData =
} else if (txData.hexData) {
// When no decoded data, display raw hex data
decodedData =
From 99e4b2b946f4efa10b089c187700a115f67358c9 Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Thu, 22 Aug 2024 16:01:27 +0200
Subject: [PATCH 19/81] 1.41.3
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index ef8930c3b1..f68b7e24ca 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.41.2",
+ "version": "1.41.3",
"type": "module",
"scripts": {
"dev": "next dev",
From 225043182894eff60b4d618ef188da0b1cdc422e Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Fri, 23 Aug 2024 07:02:13 +0200
Subject: [PATCH 20/81] Fix: limit safeViewRedirectURL redirects to Safe App
URLs (#4085)
---
.../new-safe/create/logic/index.test.ts | 25 ++++++++++++++++++-
src/components/new-safe/create/logic/index.ts | 7 ++----
.../create/steps/StatusStep/index.tsx | 5 +++-
3 files changed, 30 insertions(+), 7 deletions(-)
diff --git a/src/components/new-safe/create/logic/index.test.ts b/src/components/new-safe/create/logic/index.test.ts
index 74159bcb1f..8d93077d34 100644
--- a/src/components/new-safe/create/logic/index.test.ts
+++ b/src/components/new-safe/create/logic/index.test.ts
@@ -5,7 +5,7 @@ import type { CompatibilityFallbackHandlerContractImplementationType } from '@sa
import { EMPTY_DATA, ZERO_ADDRESS } from '@safe-global/protocol-kit/dist/src/utils/constants'
import * as web3 from '@/hooks/wallets/web3'
import * as sdkHelpers from '@/services/tx/tx-sender/sdk'
-import { relaySafeCreation } from '@/components/new-safe/create/logic/index'
+import { getRedirect, relaySafeCreation } from '@/components/new-safe/create/logic/index'
import { relayTransaction } from '@safe-global/safe-gateway-typescript-sdk'
import { toBeHex } from 'ethers'
import {
@@ -103,4 +103,27 @@ describe('createNewSafeViaRelayer', () => {
expect(relaySafeCreation(mockChainInfo, [owner1, owner2], 1, 69)).rejects.toEqual(relayFailedError)
})
+
+ describe('getRedirect', () => {
+ it("should redirect to home for any redirect that doesn't start with /apps", () => {
+ const expected = {
+ pathname: '/home',
+ query: {
+ safe: 'sep:0x1234',
+ },
+ }
+ expect(getRedirect('sep', '0x1234', 'https://google.com')).toEqual(expected)
+ expect(getRedirect('sep', '0x1234', '/queue')).toEqual(expected)
+ })
+
+ it('should redirect to an app if an app URL is passed', () => {
+ expect(getRedirect('sep', '0x1234', '/apps?appUrl=https://safe-eth.everstake.one/?chain=eth')).toEqual(
+ '/apps?appUrl=https://safe-eth.everstake.one/?chain=eth&safe=sep:0x1234',
+ )
+
+ expect(getRedirect('sep', '0x1234', '/apps?appUrl=https://safe-eth.everstake.one')).toEqual(
+ '/apps?appUrl=https://safe-eth.everstake.one&safe=sep:0x1234',
+ )
+ })
+ })
})
diff --git a/src/components/new-safe/create/logic/index.ts b/src/components/new-safe/create/logic/index.ts
index 1be9d299bd..c22e8fcb12 100644
--- a/src/components/new-safe/create/logic/index.ts
+++ b/src/components/new-safe/create/logic/index.ts
@@ -157,17 +157,14 @@ export const getRedirect = (
if (!chainPrefix) return AppRoutes.index
// Go to the dashboard if no specific redirect is provided
- if (!redirectUrl) {
+ if (!redirectUrl || !redirectUrl.startsWith(AppRoutes.apps.index)) {
return { pathname: AppRoutes.home, query: { safe: address } }
}
// Otherwise, redirect to the provided URL (e.g. from a Safe App)
// Track the redirect to Safe App
- // TODO: Narrow this down to /apps only
- if (redirectUrl.includes('apps')) {
- trackEvent(SAFE_APPS_EVENTS.SHARED_APP_OPEN_AFTER_SAFE_CREATION)
- }
+ trackEvent(SAFE_APPS_EVENTS.SHARED_APP_OPEN_AFTER_SAFE_CREATION)
// We're prepending the safe address directly here because the `router.push` doesn't parse
// The URL for already existing query params
diff --git a/src/components/new-safe/create/steps/StatusStep/index.tsx b/src/components/new-safe/create/steps/StatusStep/index.tsx
index d7c218136c..cd896b7963 100644
--- a/src/components/new-safe/create/steps/StatusStep/index.tsx
+++ b/src/components/new-safe/create/steps/StatusStep/index.tsx
@@ -54,7 +54,10 @@ export const CreateSafeStatus = ({
if (status === SafeCreationEvent.SUCCESS) {
dispatch(updateAddressBook(chain.chainId, safeAddress, data.name, data.owners, data.threshold))
- router.push(getRedirect(chain.shortName, safeAddress, router.query?.safeViewRedirectURL))
+ const redirect = getRedirect(chain.shortName, safeAddress, router.query?.safeViewRedirectURL)
+ if (typeof redirect !== 'string' || redirect.startsWith('/')) {
+ router.push(redirect)
+ }
}
}, [dispatch, chain, data.name, data.owners, data.threshold, router, safeAddress, status])
From 95d24e8bdc2772e525f6271fa934b24c9fb564a4 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 08:32:24 +0200
Subject: [PATCH 21/81] Chore(deps-dev): Bump @openzeppelin/contracts (#4086)
Bumps the npm_and_yarn group with 1 update: [@openzeppelin/contracts](https://github.com/OpenZeppelin/openzeppelin-contracts).
Updates `@openzeppelin/contracts` from 4.9.6 to 5.0.2
- [Release notes](https://github.com/OpenZeppelin/openzeppelin-contracts/releases)
- [Changelog](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/CHANGELOG.md)
- [Commits](https://github.com/OpenZeppelin/openzeppelin-contracts/compare/v4.9.6...v5.0.2)
---
updated-dependencies:
- dependency-name: "@openzeppelin/contracts"
dependency-type: direct:development
dependency-group: npm_and_yarn
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 13 ++++---------
2 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/package.json b/package.json
index 152c95a91a..ba6695926c 100644
--- a/package.json
+++ b/package.json
@@ -99,7 +99,7 @@
"@cowprotocol/app-data": "^2.1.0",
"@faker-js/faker": "^8.1.0",
"@next/bundle-analyzer": "^13.5.6",
- "@openzeppelin/contracts": "^4.9.6",
+ "@openzeppelin/contracts": "^5.0.2",
"@safe-global/safe-core-sdk-types": "^5.0.1",
"@sentry/types": "^7.74.0",
"@storybook/addon-designs": "^8.0.0",
diff --git a/yarn.lock b/yarn.lock
index a6e4dbd650..e4749085be 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3848,15 +3848,10 @@
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz#3e5321a2ecdd0b206064356798c21225b6ec7105"
integrity sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ==
-"@openzeppelin/contracts@^4.9.6":
- version "4.9.6"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677"
- integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==
-
-"@openzeppelin/contracts@^5.0.0":
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.0.tgz#ee0e4b4564f101a5c4ee398cd4d73c0bd92b289c"
- integrity sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw==
+"@openzeppelin/contracts@^5.0.0", "@openzeppelin/contracts@^5.0.2":
+ version "5.0.2"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.2.tgz#b1d03075e49290d06570b2fd42154d76c2a5d210"
+ integrity sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==
"@parcel/watcher-android-arm64@2.3.0":
version "2.3.0"
From b7323fb41a533b373bad73b0ee771cd618ad7194 Mon Sep 17 00:00:00 2001
From: Daniel Dimitrov
Date: Fri, 23 Aug 2024 09:56:41 +0200
Subject: [PATCH 22/81] refactor: usage of getTransactionDetails (#4020)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* refactor: usage of getTransactionDetails
I’ve moved the usage of getTransactionDetails to rtk query. This has
the benefit of caching the result and multiple components relying on
that data don’t have to re-request the same data as it will be available
in the redux store.
In addition to this, this change fixes a bug in the txDetails component.
We were polling for the swap status, but due to the way
useIntervalCounter works, we were causing component rerenders no matter
if the tx was a swap or not.
* Update src/components/transactions/TxDetails/index.tsx
Co-authored-by: Usame Algan <5880855+usame-algan@users.noreply.github.com>
* fix: add back POLLING_INTERVAL const
* refactor: use getTransactionDetails from rtk query in more places
* fix: lint error
* fix: crash when refetching before the query is initialized
* Revert "Chore(deps-dev): Bump @openzeppelin/contracts (#4086)"
This reverts commit 95d24e8bdc2772e525f6271fa934b24c9fb564a4.
* prettier
---------
Co-authored-by: Usame Algan <5880855+usame-algan@users.noreply.github.com>
Co-authored-by: Usame Algan
Co-authored-by: katspaugh
---
package.json | 2 +-
.../transactions/SingleTx/index.tsx | 41 ++++----
.../transactions/TxDetails/index.tsx | 37 ++++----
.../flows/ExecuteBatch/ReviewBatch.tsx | 23 +++--
src/components/tx/DecodedTx/index.tsx | 22 ++++-
src/components/tx/SignOrExecuteForm/index.tsx | 28 ++++--
.../speedup/components/SpeedUpModal.tsx | 7 +-
src/hooks/__tests__/useTxTracking.test.ts | 16 ++--
src/hooks/useTxNotifications.ts | 9 +-
src/hooks/useTxTracking.ts | 10 +-
.../analytics/__tests__/tx-tracking.test.ts | 95 ++++++++++---------
src/services/analytics/tx-tracking.ts | 9 +-
src/services/transactions/index.ts | 21 +---
src/store/gateway.ts | 46 +++++++++
src/store/index.ts | 14 ++-
src/store/slices.ts | 1 +
src/utils/transactions.ts | 10 +-
yarn.lock | 13 ++-
18 files changed, 240 insertions(+), 164 deletions(-)
create mode 100644 src/store/gateway.ts
diff --git a/package.json b/package.json
index ebd88d338a..2904ab1250 100644
--- a/package.json
+++ b/package.json
@@ -99,7 +99,7 @@
"@cowprotocol/app-data": "^2.1.0",
"@faker-js/faker": "^8.1.0",
"@next/bundle-analyzer": "^13.5.6",
- "@openzeppelin/contracts": "^5.0.2",
+ "@openzeppelin/contracts": "^4.9.6",
"@safe-global/safe-core-sdk-types": "^5.0.1",
"@sentry/types": "^7.74.0",
"@storybook/addon-designs": "^8.0.0",
diff --git a/src/components/transactions/SingleTx/index.tsx b/src/components/transactions/SingleTx/index.tsx
index 07f9d33dad..c2bd9e52a6 100644
--- a/src/components/transactions/SingleTx/index.tsx
+++ b/src/components/transactions/SingleTx/index.tsx
@@ -1,12 +1,11 @@
import ErrorMessage from '@/components/tx/ErrorMessage'
import { useRouter } from 'next/router'
import useSafeInfo from '@/hooks/useSafeInfo'
-import useAsync from '@/hooks/useAsync'
import type { Label, Transaction, TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { LabelValue } from '@safe-global/safe-gateway-typescript-sdk'
-import { getTransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { sameAddress } from '@/utils/addresses'
import type { ReactElement } from 'react'
+import { useEffect } from 'react'
import { makeTxFromDetails } from '@/utils/transactions'
import { TxListGrid } from '@/components/transactions/TxList'
import ExpandableTransactionItem, {
@@ -14,6 +13,9 @@ import ExpandableTransactionItem, {
} from '@/components/transactions/TxListItem/ExpandableTransactionItem'
import GroupLabel from '../GroupLabel'
import { isMultisigDetailedExecutionInfo } from '@/utils/transaction-guards'
+import { useGetTransactionDetailsQuery } from '@/store/gateway'
+import { skipToken } from '@reduxjs/toolkit/query/react'
+import { asError } from '@/services/exceptions/utils'
const SingleTxGrid = ({ txDetails }: { txDetails: TransactionDetails }): ReactElement => {
const tx: Transaction = makeTxFromDetails(txDetails)
@@ -40,25 +42,30 @@ const SingleTx = () => {
const transactionId = Array.isArray(id) ? id[0] : id
const { safe, safeAddress } = useSafeInfo()
- const [txDetails, txDetailsError] = useAsync(
- () => {
- if (!transactionId || !safeAddress) return
-
- return getTransactionDetails(safe.chainId, transactionId).then((details) => {
- // If the transaction is not related to the current safe, throw an error
- if (!sameAddress(details.safeAddress, safeAddress)) {
- return Promise.reject(new Error('Transaction with this id was not found in this Safe Account'))
+ let {
+ data: txDetails,
+ error: txDetailsError,
+ refetch,
+ isUninitialized,
+ } = useGetTransactionDetailsQuery(
+ transactionId && safe.chainId
+ ? {
+ chainId: safe.chainId,
+ txId: transactionId,
}
- return details
- })
- },
- // eslint-disable-next-line react-hooks/exhaustive-deps
- [transactionId, safe.chainId, safe.txQueuedTag, safe.txHistoryTag, safeAddress],
- false,
+ : skipToken,
)
+ useEffect(() => {
+ !isUninitialized && refetch()
+ }, [safe.txHistoryTag, safe.txQueuedTag, safeAddress, refetch, isUninitialized])
+
+ if (txDetails && !sameAddress(txDetails.safeAddress, safeAddress)) {
+ txDetailsError = new Error('Transaction with this id was not found in this Safe Account')
+ }
+
if (txDetailsError) {
- return Failed to load transaction
+ return Failed to load transaction
}
if (txDetails) {
diff --git a/src/components/transactions/TxDetails/index.tsx b/src/components/transactions/TxDetails/index.tsx
index 948dcda5e3..1d9a4febf4 100644
--- a/src/components/transactions/TxDetails/index.tsx
+++ b/src/components/transactions/TxDetails/index.tsx
@@ -1,16 +1,12 @@
-import { POLLING_INTERVAL } from '@/config/constants'
import useIsExpiredSwap from '@/features/swap/hooks/useIsExpiredSwap'
-import useIntervalCounter from '@/hooks/useIntervalCounter'
-import React, { type ReactElement } from 'react'
+import React, { type ReactElement, useEffect } from 'react'
import type { TransactionDetails, TransactionSummary } from '@safe-global/safe-gateway-typescript-sdk'
-import { getTransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { Box, CircularProgress, Typography } from '@mui/material'
import TxSigners from '@/components/transactions/TxSigners'
import Summary from '@/components/transactions/TxDetails/Summary'
import TxData from '@/components/transactions/TxDetails/TxData'
import useChainId from '@/hooks/useChainId'
-import useAsync from '@/hooks/useAsync'
import {
isAwaitingExecution,
isOrderTxInfo,
@@ -38,6 +34,9 @@ import { isImitation, isTrustedTx } from '@/utils/transactions'
import { useHasFeature } from '@/hooks/useChains'
import { FEATURES } from '@/utils/chains'
import { SwapOrder } from '@/features/swap/components/SwapOrder'
+import { useGetTransactionDetailsQuery } from '@/store/gateway'
+import { asError } from '@/services/exceptions/utils'
+import { POLLING_INTERVAL } from '@/config/constants'
export const NOT_AVAILABLE = 'n/a'
@@ -159,21 +158,23 @@ const TxDetails = ({
const chainId = useChainId()
const { safe } = useSafeInfo()
- const [pollCount] = useIntervalCounter(POLLING_INTERVAL)
- const swapPollCount = isOpenSwapOrder(txSummary.txInfo) ? pollCount : 0
-
- const [txDetailsData, error, loading] = useAsync(
- async () => {
- if (txDetails && swapPollCount <= 0) {
- return txDetails
- }
- return getTransactionDetails(chainId, txSummary.id)
+ const {
+ data: txDetailsData,
+ error,
+ isLoading: loading,
+ refetch,
+ isUninitialized,
+ } = useGetTransactionDetailsQuery(
+ { chainId, txId: txSummary.id },
+ {
+ pollingInterval: isOpenSwapOrder(txSummary.txInfo) ? POLLING_INTERVAL : undefined,
},
- // eslint-disable-next-line react-hooks/exhaustive-deps
- [txDetails, chainId, txSummary.id, safe.txQueuedTag, swapPollCount],
- false,
)
+ useEffect(() => {
+ !isUninitialized && refetch()
+ }, [safe.txQueuedTag, refetch, txDetails, isUninitialized])
+
return (
{txDetailsData ? (
@@ -185,7 +186,7 @@ const TxDetails = ({
) : (
error && (
- Couldn't load the transaction details
+ Couldn't load the transaction details
)
)}
diff --git a/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx b/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx
index 721675cf16..cd30e55d6d 100644
--- a/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx
+++ b/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx
@@ -3,7 +3,6 @@ import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import { CircularProgress, Typography, Button, CardActions, Divider, Alert } from '@mui/material'
import useAsync from '@/hooks/useAsync'
import { FEATURES } from '@/utils/chains'
-import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { getReadOnlyMultiSendCallOnlyContract } from '@/services/contracts/safeContracts'
import { useCurrentChain } from '@/hooks/useChains'
import useSafeInfo from '@/hooks/useSafeInfo'
@@ -20,7 +19,7 @@ import useOnboard from '@/hooks/wallets/useOnboard'
import { logError, Errors } from '@/services/exceptions'
import { dispatchBatchExecution, dispatchBatchExecutionRelay } from '@/services/tx/tx-sender'
import { hasRemainingRelays } from '@/utils/relaying'
-import { getTxsWithDetails, getMultiSendTxs } from '@/utils/transactions'
+import { getMultiSendTxs } from '@/utils/transactions'
import TxCard from '../../common/TxCard'
import CheckWallet from '@/components/common/CheckWallet'
import type { ExecuteBatchFlowProps } from '.'
@@ -39,6 +38,8 @@ import WalletRejectionError from '@/components/tx/SignOrExecuteForm/WalletReject
import useUserNonce from '@/components/tx/AdvancedParams/useUserNonce'
import { getLatestSafeVersion } from '@/utils/chains'
import { HexEncodedData } from '@/components/transactions/HexEncodedData'
+import { useGetMultipleTransactionDetailsQuery } from '@/store/gateway'
+import { skipToken } from '@reduxjs/toolkit/query/react'
export const ReviewBatch = ({ params }: { params: ExecuteBatchFlowProps }) => {
const [isSubmittable, setIsSubmittable] = useState
(true)
@@ -66,10 +67,18 @@ export const ReviewBatch = ({ params }: { params: ExecuteBatchFlowProps }) => {
const onboard = useOnboard()
const wallet = useWallet()
- const [txsWithDetails, error, loading] = useAsync(() => {
- if (!chain?.chainId) return
- return getTxsWithDetails(params.txs, chain.chainId)
- }, [params.txs, chain?.chainId])
+ const {
+ data: txsWithDetails,
+ error,
+ isLoading: loading,
+ } = useGetMultipleTransactionDetailsQuery(
+ chain?.chainId && params.txs.length
+ ? {
+ chainId: chain.chainId,
+ txIds: params.txs.map((tx) => tx.transaction.id),
+ }
+ : skipToken,
+ )
const [multiSendContract] = useAsync(async () => {
if (!safe.version) return
@@ -203,7 +212,7 @@ export const ReviewBatch = ({ params }: { params: ExecuteBatchFlowProps }) => {
{error && (
-
+
This transaction will most likely fail. To save gas costs, avoid creating the transaction.
)}
diff --git a/src/components/tx/DecodedTx/index.tsx b/src/components/tx/DecodedTx/index.tsx
index a68c7b615a..ac3ddfcd8e 100644
--- a/src/components/tx/DecodedTx/index.tsx
+++ b/src/components/tx/DecodedTx/index.tsx
@@ -4,6 +4,7 @@ import { Accordion, AccordionDetails, AccordionSummary, Box, Skeleton, Stack } f
import { OperationType, type SafeTransaction } from '@safe-global/safe-core-sdk-types'
import type { DecodedDataResponse } from '@safe-global/safe-gateway-typescript-sdk'
import { Operation } from '@safe-global/safe-gateway-typescript-sdk'
+import useChainId from '@/hooks/useChainId'
import ErrorMessage from '../ErrorMessage'
import Summary, { PartialSummary } from '@/components/transactions/TxDetails/Summary'
import { trackEvent, MODALS_EVENTS } from '@/services/analytics'
@@ -12,7 +13,9 @@ import ExpandMoreIcon from '@mui/icons-material/ExpandMore'
import DecodedData from '@/components/transactions/TxDetails/TxData/DecodedData'
import accordionCss from '@/styles/accordion.module.css'
import HelpToolTip from './HelpTooltip'
-import useTxDetails from '@/hooks/useTxDetails'
+import { useGetTransactionDetailsQuery } from '@/store/gateway'
+import { skipToken } from '@reduxjs/toolkit/query/react'
+import { asError } from '@/services/exceptions/utils'
type DecodedTxProps = {
tx?: SafeTransaction
@@ -39,8 +42,21 @@ const DecodedTx = ({
showMethodCall = false,
}: DecodedTxProps): ReactElement => {
const isMultisend = !!decodedData?.parameters?.[0]?.valueDecoded
+ const chainId = useChainId()
const isMethodCallInAdvanced = !showMethodCall || isMultisend
- const [txDetails, txDetailsError, txDetailsLoading] = useTxDetails(txId)
+
+ const {
+ data: txDetails,
+ error: txDetailsError,
+ isLoading: txDetailsLoading,
+ } = useGetTransactionDetailsQuery(
+ chainId && txId
+ ? {
+ chainId,
+ txId,
+ }
+ : skipToken,
+ )
const onChangeExpand = (_: SyntheticEvent, expanded: boolean) => {
trackEvent({ ...MODALS_EVENTS.TX_DETAILS, label: expanded ? 'Open' : 'Close' })
@@ -103,7 +119,7 @@ const DecodedTx = ({
{txDetailsLoading && }
{txDetailsError && (
- Failed loading all transaction details
+ Failed loading all transaction details
)}
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index e7326adcd5..ff3c299f38 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -33,10 +33,13 @@ import SwapOrderConfirmationView from '@/features/swap/components/SwapOrderConfi
import { isSettingTwapFallbackHandler } from '@/features/swap/helpers/utils'
import { TwapFallbackHandlerWarning } from '@/features/swap/components/TwapFallbackHandlerWarning'
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
-import useTxDetails from '@/hooks/useTxDetails'
import TxData from '@/components/transactions/TxDetails/TxData'
import { useApprovalInfos } from '../ApprovalEditor/hooks/useApprovalInfos'
+import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
+import { useGetTransactionDetailsQuery, useLazyGetTransactionDetailsQuery } from '@/store/gateway'
+import { skipToken } from '@reduxjs/toolkit/query/react'
+
export type SubmitCallback = (txId: string, isExecuted?: boolean) => void
export type SignOrExecuteProps = {
@@ -54,9 +57,8 @@ export type SignOrExecuteProps = {
showMethodCall?: boolean
}
-const trackTxEvents = async (
- chainId: string,
- txId: string,
+const trackTxEvents = (
+ details: TransactionDetails | undefined,
isCreation: boolean,
isExecuted: boolean,
isRoleExecution: boolean,
@@ -64,8 +66,7 @@ const trackTxEvents = async (
const creationEvent = isRoleExecution ? TX_EVENTS.CREATE_VIA_ROLE : TX_EVENTS.CREATE
const executionEvent = isRoleExecution ? TX_EVENTS.EXECUTE_VIA_ROLE : TX_EVENTS.EXECUTE
const event = isCreation ? creationEvent : isExecuted ? executionEvent : TX_EVENTS.CONFIRM
-
- const txType = await getTransactionTrackingType(chainId, txId)
+ const txType = getTransactionTrackingType(details)
trackEvent({ ...event, label: txType })
// Immediate execution on creation
@@ -93,8 +94,16 @@ export const SignOrExecuteForm = ({
const [decodedData] = useDecodeTx(safeTx)
const isBatchable = props.isBatchable !== false && safeTx && !isDelegateCall(safeTx)
const isSwapOrder = isConfirmationViewOrder(decodedData)
- const [txDetails] = useTxDetails(props.txId)
+ const { data: txDetails } = useGetTransactionDetailsQuery(
+ chainId && props.txId
+ ? {
+ chainId,
+ txId: props.txId,
+ }
+ : skipToken,
+ )
const showTxDetails = props.txId && txDetails && !isCustomTxInfo(txDetails.txInfo)
+ const [trigger] = useLazyGetTransactionDetailsQuery()
const [readableApprovals] = useApprovalInfos({ safeTransaction: safeTx })
const isApproval = readableApprovals && readableApprovals.length > 0
@@ -122,10 +131,11 @@ export const SignOrExecuteForm = ({
async (txId: string, isExecuted = false, isRoleExecution = false) => {
onSubmit?.(txId, isExecuted)
+ const { data: details } = await trigger({ chainId, txId })
// Track tx event
- trackTxEvents(chainId, txId, isCreation, isExecuted, isRoleExecution)
+ trackTxEvents(details, isCreation, isExecuted, isRoleExecution)
},
- [chainId, isCreation, onSubmit],
+ [chainId, isCreation, onSubmit, trigger],
)
const onRoleExecutionSubmit = useCallback(
diff --git a/src/features/speedup/components/SpeedUpModal.tsx b/src/features/speedup/components/SpeedUpModal.tsx
index d4a054a93e..6f1a0eca19 100644
--- a/src/features/speedup/components/SpeedUpModal.tsx
+++ b/src/features/speedup/components/SpeedUpModal.tsx
@@ -27,6 +27,7 @@ import { TX_EVENTS } from '@/services/analytics/events/transactions'
import { getTransactionTrackingType } from '@/services/analytics/tx-tracking'
import { trackError } from '@/services/exceptions'
import ErrorCodes from '@/services/exceptions/ErrorCodes'
+import { useLazyGetTransactionDetailsQuery } from '@/store/gateway'
type Props = {
open: boolean
@@ -58,7 +59,7 @@ export const SpeedUpModal = ({
const safeAddress = useSafeAddress()
const hasActions = signerAddress && signerAddress === wallet?.address
const dispatch = useAppDispatch()
-
+ const [trigger] = useLazyGetTransactionDetailsQuery()
const isDisabled = waitingForConfirmation || !wallet || !speedUpFee || !onboard
const [safeTx] = useAsync(async () => {
if (!chainInfo?.chainId || !safeAddress) {
@@ -101,7 +102,8 @@ export const SpeedUpModal = ({
wallet.address,
safeAddress,
)
- const txType = await getTransactionTrackingType(chainInfo.chainId, txId)
+ const { data: details } = await trigger({ chainId: chainInfo.chainId, txId })
+ const txType = getTransactionTrackingType(details)
trackEvent({ ...TX_EVENTS.SPEED_UP, label: txType })
} else {
await dispatchCustomTxSpeedUp(
@@ -152,6 +154,7 @@ export const SpeedUpModal = ({
txId,
wallet,
safeTx,
+ trigger,
])
if (!hasActions) {
diff --git a/src/hooks/__tests__/useTxTracking.test.ts b/src/hooks/__tests__/useTxTracking.test.ts
index bd7834e8a3..2b4939484d 100644
--- a/src/hooks/__tests__/useTxTracking.test.ts
+++ b/src/hooks/__tests__/useTxTracking.test.ts
@@ -2,7 +2,7 @@ import { act, renderHook } from '@/tests/test-utils'
import { txDispatch, TxEvent } from '@/services/tx/txEvents'
import { useTxTracking } from '../useTxTracking'
import { trackEvent, WALLET_EVENTS } from '@/services/analytics'
-import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
+import { getTransactionDetails, type TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { faker } from '@faker-js/faker'
jest.mock('@/services/analytics', () => ({
@@ -10,11 +10,17 @@ jest.mock('@/services/analytics', () => ({
trackEvent: jest.fn(),
}))
-jest.mock('@/services/transactions', () => ({
- getTxDetails: jest.fn(() => Promise.resolve({ safeAppInfo: { url: 'google.com' } } as unknown as TransactionDetails)),
+jest.mock('@safe-global/safe-gateway-typescript-sdk', () => ({
+ ...jest.requireActual('@safe-global/safe-gateway-typescript-sdk'),
+ getTransactionDetails: jest.fn(),
}))
describe('useTxTracking', () => {
+ beforeEach(() => {
+ ;(getTransactionDetails as jest.Mock).mockResolvedValue({
+ safeAppInfo: { url: 'google.com' },
+ } as unknown as TransactionDetails)
+ })
it('should track the ONCHAIN_INTERACTION event', async () => {
renderHook(() => useTxTracking())
@@ -35,10 +41,6 @@ describe('useTxTracking', () => {
})
})
- beforeEach(() => {
- // jest.resetAllMocks()
- })
-
it('should track relayed executions', () => {
renderHook(() => useTxTracking())
diff --git a/src/hooks/useTxNotifications.ts b/src/hooks/useTxNotifications.ts
index 98967e59e8..5311a8e8a6 100644
--- a/src/hooks/useTxNotifications.ts
+++ b/src/hooks/useTxNotifications.ts
@@ -12,9 +12,9 @@ import useIsSafeOwner from '@/hooks/useIsSafeOwner'
import useWallet from './wallets/useWallet'
import useSafeAddress from './useSafeAddress'
import { getExplorerLink } from '@/utils/gateway'
-import { getTxDetails } from '@/services/transactions'
import { isWalletRejection } from '@/utils/wallets'
import { getTxLink } from '@/utils/tx-link'
+import { useLazyGetTransactionDetailsQuery } from '@/store/gateway'
const TxNotifications = {
[TxEvent.SIGN_FAILED]: 'Failed to sign. Please try again.',
@@ -46,6 +46,7 @@ const useTxNotifications = (): void => {
const dispatch = useAppDispatch()
const chain = useCurrentChain()
const safeAddress = useSafeAddress()
+ const [trigger] = useLazyGetTransactionDetailsQuery()
/**
* Show notifications of a transaction's lifecycle
@@ -70,8 +71,8 @@ const useTxNotifications = (): void => {
const id = txId || txHash
if (id) {
try {
- const txDetails = await getTxDetails(chain.chainId, id)
- humanDescription = txDetails.txInfo.humanDescription || humanDescription
+ const { data: txDetails } = await trigger({ chainId: chain.chainId, txId: id })
+ humanDescription = txDetails?.txInfo.humanDescription || humanDescription
} catch {}
}
@@ -95,7 +96,7 @@ const useTxNotifications = (): void => {
return () => {
unsubFns.forEach((unsub) => unsub())
}
- }, [dispatch, safeAddress, chain])
+ }, [dispatch, safeAddress, chain, trigger])
/**
* If there's at least one transaction awaiting confirmations, show a notification for it
diff --git a/src/hooks/useTxTracking.ts b/src/hooks/useTxTracking.ts
index 857e89f284..44a1e570dd 100644
--- a/src/hooks/useTxTracking.ts
+++ b/src/hooks/useTxTracking.ts
@@ -1,8 +1,8 @@
import { trackEvent, WALLET_EVENTS } from '@/services/analytics'
-import { getTxDetails } from '@/services/transactions'
import { TxEvent, txSubscribe } from '@/services/tx/txEvents'
import { useEffect } from 'react'
import useChainId from './useChainId'
+import { useLazyGetTransactionDetailsQuery } from '@/store/gateway'
const events = {
[TxEvent.SIGNED]: WALLET_EVENTS.OFFCHAIN_SIGNATURE,
@@ -14,6 +14,8 @@ const events = {
export const useTxTracking = (): void => {
const chainId = useChainId()
+ const [trigger] = useLazyGetTransactionDetailsQuery()
+
useEffect(() => {
const unsubFns = Object.entries(events).map(([txEvent, analyticsEvent]) =>
txSubscribe(txEvent as TxEvent, async (detail) => {
@@ -25,8 +27,8 @@ export const useTxTracking = (): void => {
if (id) {
try {
- const txDetails = await getTxDetails(chainId, id)
- origin = txDetails.safeAppInfo?.url || ''
+ const { data: txDetails } = await trigger({ chainId, txId: id })
+ origin = txDetails?.safeAppInfo?.url || ''
} catch {}
}
@@ -40,5 +42,5 @@ export const useTxTracking = (): void => {
return () => {
unsubFns.forEach((unsub) => unsub())
}
- }, [chainId])
+ }, [chainId, trigger])
}
diff --git a/src/services/analytics/__tests__/tx-tracking.test.ts b/src/services/analytics/__tests__/tx-tracking.test.ts
index d8c58b3219..90e5d6492e 100644
--- a/src/services/analytics/__tests__/tx-tracking.test.ts
+++ b/src/services/analytics/__tests__/tx-tracking.test.ts
@@ -1,176 +1,177 @@
-import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
-import { SettingsInfoType, TransactionInfoType, TransactionTokenType } from '@safe-global/safe-gateway-typescript-sdk'
+import {
+ SettingsInfoType,
+ type TransactionDetails,
+ TransactionInfoType,
+ TransactionTokenType,
+} from '@safe-global/safe-gateway-typescript-sdk'
import { getTransactionTrackingType } from '../tx-tracking'
-import * as txDetailsModule from '@/services/transactions'
import { TX_TYPES } from '../events/transactions'
-const getMockTxType = (txDetails: unknown) => {
- jest.spyOn(txDetailsModule, 'getTxDetails').mockImplementation(() => Promise.resolve(txDetails as TransactionDetails))
- return getTransactionTrackingType('1', '0x123')
-}
-
describe('getTransactionTrackingType', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+ })
it('should return transfer_token for native token transfers', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.TRANSFER,
transferInfo: {
type: TransactionTokenType.NATIVE_COIN,
},
},
- } as unknown)
-
+ } as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.transfer_token)
})
it('should return transfer_token for ERC20 token transfers', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.TRANSFER,
transferInfo: {
type: TransactionTokenType.ERC20,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.transfer_token)
})
it('should return transfer_nft for ERC721 token transfers', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.TRANSFER,
transferInfo: {
type: TransactionTokenType.ERC721,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.transfer_nft)
})
it('should return owner_add for add owner settings changes', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.SETTINGS_CHANGE,
settingsInfo: {
type: SettingsInfoType.ADD_OWNER,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.owner_add)
})
it('should return owner_remove for remove owner settings changes', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.SETTINGS_CHANGE,
settingsInfo: {
type: SettingsInfoType.REMOVE_OWNER,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.owner_remove)
})
it('should return owner_swap for swap owner settings changes', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.SETTINGS_CHANGE,
settingsInfo: {
type: SettingsInfoType.SWAP_OWNER,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.owner_swap)
})
it('should return owner_threshold_change for change threshold settings changes', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.SETTINGS_CHANGE,
settingsInfo: {
type: SettingsInfoType.CHANGE_THRESHOLD,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.owner_threshold_change)
})
it('should return module_remove for disable module settings changes', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.SETTINGS_CHANGE,
settingsInfo: {
type: SettingsInfoType.DISABLE_MODULE,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.module_remove)
})
it('should return guard_remove for delete guard settings changes', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.SETTINGS_CHANGE,
settingsInfo: {
type: SettingsInfoType.DELETE_GUARD,
},
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.guard_remove)
})
it('should return rejection for rejection transactions', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.CUSTOM,
isCancellation: true,
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.rejection)
})
it('should return walletconnect for transactions w/o safeAppInfo', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.CUSTOM,
},
safeAppInfo: null,
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.walletconnect)
})
it('should return safeapps for safeapps transactions', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.CUSTOM,
},
safeAppInfo: {
url: 'https://gnosis-safe.io/app',
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual('https://gnosis-safe.io/app')
})
it('should return batch for multisend transactions', async () => {
- const txType = await getMockTxType({
+ const details = {
txInfo: {
type: TransactionInfoType.CUSTOM,
methodName: 'multiSend',
actionCount: 2,
},
- } as unknown)
-
+ } as unknown as TransactionDetails
+ const txType = getTransactionTrackingType(details)
expect(txType).toEqual(TX_TYPES.batch)
})
})
diff --git a/src/services/analytics/tx-tracking.ts b/src/services/analytics/tx-tracking.ts
index 0f9af3359b..9b74293481 100644
--- a/src/services/analytics/tx-tracking.ts
+++ b/src/services/analytics/tx-tracking.ts
@@ -1,5 +1,4 @@
import { TX_TYPES } from '@/services/analytics/events/transactions'
-import { getTxDetails } from '@/services/transactions'
import { SettingsInfoType, type TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import {
isERC721Transfer,
@@ -11,12 +10,8 @@ import {
isSwapOrderTxInfo,
} from '@/utils/transaction-guards'
-export const getTransactionTrackingType = async (chainId: string, txId: string): Promise => {
- let details: TransactionDetails
-
- try {
- details = await getTxDetails(chainId, txId)
- } catch {
+export const getTransactionTrackingType = (details: TransactionDetails | undefined): string => {
+ if (!details) {
return TX_TYPES.custom
}
diff --git a/src/services/transactions/index.ts b/src/services/transactions/index.ts
index d9fb50fc40..bf4d7a39b1 100644
--- a/src/services/transactions/index.ts
+++ b/src/services/transactions/index.ts
@@ -1,26 +1,7 @@
-import memoize from 'lodash/memoize'
-import {
- getModuleTransactions,
- getTransactionDetails,
- getTransactionHistory,
-} from '@safe-global/safe-gateway-typescript-sdk'
+import { getModuleTransactions, getTransactionHistory } from '@safe-global/safe-gateway-typescript-sdk'
export const getTimezoneOffset = () => new Date().getTimezoneOffset() * 60 * -1000
-/**
- * Fetch and memoize transaction details from Safe Gateway
- *
- * @param chainId Chain id
- * @param id Transaction id or hash
- * @returns Transaction details
- */
-export const getTxDetails = memoize(
- (chainId: string, id: string) => {
- return getTransactionDetails(chainId, id)
- },
- (id: string, chainId: string) => `${chainId}-${id}`,
-)
-
export const getTxHistory = (
chainId: string,
safeAddress: string,
diff --git a/src/store/gateway.ts b/src/store/gateway.ts
new file mode 100644
index 0000000000..97eafa294e
--- /dev/null
+++ b/src/store/gateway.ts
@@ -0,0 +1,46 @@
+import { createApi } from '@reduxjs/toolkit/query/react'
+
+import { getTransactionDetails, type TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
+import type { BaseQueryFn } from '@reduxjs/toolkit/dist/query/baseQueryTypes'
+import type { FetchBaseQueryError } from '@reduxjs/toolkit/dist/query/react'
+
+const noopBaseQuery: BaseQueryFn<
+ unknown, // QueryArg type
+ unknown, // ResultType
+ FetchBaseQueryError, // ErrorType
+ {}, // DefinitionExtraOptions
+ {} // Meta
+> = async () => ({ data: null })
+
+export const gatewayApi = createApi({
+ reducerPath: 'gatewayApi',
+ baseQuery: noopBaseQuery,
+ endpoints: (builder) => ({
+ getTransactionDetails: builder.query({
+ async queryFn({ chainId, txId }) {
+ try {
+ const txDetails = await getTransactionDetails(chainId, txId)
+ return { data: txDetails }
+ } catch (error) {
+ return { error: error as FetchBaseQueryError }
+ }
+ },
+ }),
+ getMultipleTransactionDetails: builder.query({
+ async queryFn({ chainId, txIds }) {
+ try {
+ const txDetails = await Promise.all(txIds.map((txId) => getTransactionDetails(chainId, txId)))
+ return { data: txDetails }
+ } catch (error) {
+ return { error: error as FetchBaseQueryError }
+ }
+ },
+ }),
+ }),
+})
+
+export const {
+ useGetTransactionDetailsQuery,
+ useGetMultipleTransactionDetailsQuery,
+ useLazyGetTransactionDetailsQuery,
+} = gatewayApi
diff --git a/src/store/index.ts b/src/store/index.ts
index 63521b688f..7ac81800a5 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -3,8 +3,10 @@ import {
combineReducers,
createListenerMiddleware,
type ThunkAction,
- type UnknownAction,
+ type Action,
type Middleware,
+ type EnhancedStore,
+ type ThunkDispatch,
} from '@reduxjs/toolkit'
import { useDispatch, useSelector, type TypedUseSelectorHook } from 'react-redux'
import merge from 'lodash/merge'
@@ -45,6 +47,7 @@ const rootReducer = combineReducers({
[slices.undeployedSafesSlice.name]: slices.undeployedSafesSlice.reducer,
[slices.swapParamsSlice.name]: slices.swapParamsSlice.reducer,
[ofacApi.reducerPath]: ofacApi.reducer,
+ [slices.gatewayApi.reducerPath]: slices.gatewayApi.reducer,
})
const persistedSlices: (keyof Partial)[] = [
@@ -68,11 +71,12 @@ export const getPersistedState = () => {
export const listenerMiddlewareInstance = createListenerMiddleware()
-const middleware: Middleware[] = [
+const middleware: Middleware<{}, RootState>[] = [
persistState(persistedSlices),
broadcastState(persistedSlices),
listenerMiddlewareInstance.middleware,
ofacApi.middleware,
+ slices.gatewayApi.middleware,
]
const listeners = [safeMessagesListener, txHistoryListener, txQueueListener, swapOrderListener, swapOrderStatusListener]
@@ -91,7 +95,7 @@ export const _hydrationReducer: typeof rootReducer = (state, action) => {
return rootReducer(state, action) as RootState
}
-export const makeStore = (initialState?: Partial) => {
+export const makeStore = (initialState?: Partial): EnhancedStore => {
const store = configureStore({
reducer: _hydrationReducer,
middleware: (getDefaultMiddleware) => {
@@ -107,9 +111,9 @@ export const makeStore = (initialState?: Partial) => {
return store
}
-export type AppDispatch = ReturnType['dispatch']
export type RootState = ReturnType
-export type AppThunk = ThunkAction
+export type AppDispatch = ThunkDispatch & EnhancedStore['dispatch']
+export type AppThunk = ThunkAction
export const useAppDispatch = () => useDispatch()
export const useAppSelector: TypedUseSelectorHook = useSelector
diff --git a/src/store/slices.ts b/src/store/slices.ts
index 210bd7d7c5..c0dce32a5a 100644
--- a/src/store/slices.ts
+++ b/src/store/slices.ts
@@ -19,3 +19,4 @@ export * from './batchSlice'
export * from '@/features/counterfactual/store/undeployedSafesSlice'
export * from '@/features/swap/store/swapParamsSlice'
export * from './swapOrderSlice'
+export * from './gateway'
diff --git a/src/utils/transactions.ts b/src/utils/transactions.ts
index b803c2c0b7..a9fc0af7f0 100644
--- a/src/utils/transactions.ts
+++ b/src/utils/transactions.ts
@@ -10,7 +10,7 @@ import type {
TransactionListPage,
TransactionSummary,
} from '@safe-global/safe-gateway-typescript-sdk'
-import { ConflictType, getTransactionDetails, TransactionListItemType } from '@safe-global/safe-gateway-typescript-sdk'
+import { ConflictType, TransactionListItemType } from '@safe-global/safe-gateway-typescript-sdk'
import {
isERC20Transfer,
isModuleDetailedExecutionInfo,
@@ -140,14 +140,6 @@ export const getMultiSendTxs = async (
.filter(Boolean) as MetaTransactionData[]
}
-export const getTxsWithDetails = (txs: Transaction[], chainId: string) => {
- return Promise.all(
- txs.map(async (tx) => {
- return await getTransactionDetails(chainId, tx.transaction.id)
- }),
- )
-}
-
export const getTxOptions = (params: AdvancedParameters, currentChain: ChainInfo | undefined): TransactionOptions => {
const txOptions: TransactionOptions = {
gasLimit: params.gasLimit?.toString(),
diff --git a/yarn.lock b/yarn.lock
index e4749085be..a6e4dbd650 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3848,10 +3848,15 @@
resolved "https://registry.yarnpkg.com/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-5.0.2.tgz#3e5321a2ecdd0b206064356798c21225b6ec7105"
integrity sha512-0MmkHSHiW2NRFiT9/r5Lu4eJq5UJ4/tzlOgYXNAIj/ONkQTVnz22pLxDvp4C4uZ9he7ZFvGn3Driptn1/iU7tQ==
-"@openzeppelin/contracts@^5.0.0", "@openzeppelin/contracts@^5.0.2":
- version "5.0.2"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.2.tgz#b1d03075e49290d06570b2fd42154d76c2a5d210"
- integrity sha512-ytPc6eLGcHHnapAZ9S+5qsdomhjo6QBHTDRRBFfTxXIpsicMhVPouPgmUPebZZZGX7vt9USA+Z+0M0dSVtSUEA==
+"@openzeppelin/contracts@^4.9.6":
+ version "4.9.6"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677"
+ integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==
+
+"@openzeppelin/contracts@^5.0.0":
+ version "5.0.0"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-5.0.0.tgz#ee0e4b4564f101a5c4ee398cd4d73c0bd92b289c"
+ integrity sha512-bv2sdS6LKqVVMLI5+zqnNrNU/CA+6z6CmwFXm/MzmOPBRSO5reEJN7z0Gbzvs0/bv/MZZXNklubpwy3v2+azsw==
"@parcel/watcher-android-arm64@2.3.0":
version "2.3.0"
From 012243bf17bf9de6882e34e54d7b2fc643f85db6 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Fri, 23 Aug 2024 09:58:31 +0200
Subject: [PATCH 23/81] Fix: allow Safe Apps from localhost: (#4080)
---
src/config/securityHeaders.ts | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/config/securityHeaders.ts b/src/config/securityHeaders.ts
index a0870c5c09..5cd722ad69 100644
--- a/src/config/securityHeaders.ts
+++ b/src/config/securityHeaders.ts
@@ -17,7 +17,7 @@ export const ContentSecurityPolicy = `
? "'unsafe-eval'" // Dev server and cypress need unsafe-eval
: "'wasm-unsafe-eval'"
};
- frame-src http://* https://*;
+ frame-src http: https:;
style-src 'self' 'unsafe-inline' https://*.getbeamer.com https://*.googleapis.com;
font-src 'self' data:;
worker-src 'self' blob:;
From 49571f27fc479c6459ad2dcf4eec939bcb270860 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:07:10 +0200
Subject: [PATCH 24/81] Chore: create dependabot.yml (#4087)
* Create dependabot.yml
* Add github-actions
* Cean up quotes
---
.github/dependabot.yml | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
create mode 100644 .github/dependabot.yml
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..4bae3ef5f9
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,16 @@
+# To get started with Dependabot version updates, you'll need to specify which
+# package ecosystems to update and where the package manifests are located.
+# Please see the documentation for all configuration options:
+# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
+
+version: 2
+updates:
+ - package-ecosystem: 'npm'
+ directory: '/'
+ schedule:
+ interval: 'weekly'
+
+ - package-ecosystem: 'github-actions'
+ directory: '/'
+ schedule:
+ interval: 'weekly'
From a93c6edbe8dc63d9cdd0450df348b402878b0dbf Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:11:13 +0200
Subject: [PATCH 25/81] Chore(deps): Bump actions/setup-python from 3 to 5
(#4095)
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 3 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v3...v5)
---
updated-dependencies:
- dependency-name: actions/setup-python
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/e2e-hp-ondemand.yml | 2 +-
.github/workflows/e2e-ondemand.yml | 2 +-
.github/workflows/e2e-prod-ondemand.yml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/e2e-hp-ondemand.yml b/.github/workflows/e2e-hp-ondemand.yml
index 9f8ef6f958..bd1f2e95a0 100644
--- a/.github/workflows/e2e-hp-ondemand.yml
+++ b/.github/workflows/e2e-hp-ondemand.yml
@@ -31,7 +31,7 @@ jobs:
- name: Python setup
if: always()
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
diff --git a/.github/workflows/e2e-ondemand.yml b/.github/workflows/e2e-ondemand.yml
index 86acef985a..87999581e5 100644
--- a/.github/workflows/e2e-ondemand.yml
+++ b/.github/workflows/e2e-ondemand.yml
@@ -34,7 +34,7 @@ jobs:
- name: Python setup
if: always()
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
diff --git a/.github/workflows/e2e-prod-ondemand.yml b/.github/workflows/e2e-prod-ondemand.yml
index 7ce75e8f25..76fd8c5dbb 100644
--- a/.github/workflows/e2e-prod-ondemand.yml
+++ b/.github/workflows/e2e-prod-ondemand.yml
@@ -30,7 +30,7 @@ jobs:
- name: Python setup
if: always()
- uses: actions/setup-python@v3
+ uses: actions/setup-python@v5
with:
python-version: '3.x'
From 7cc1d87a8fa6c0f181c8659cc4829d0a5ede54ad Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:11:22 +0200
Subject: [PATCH 26/81] Chore(deps): Bump docker/build-push-action from 5 to 6
(#4096)
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 6.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](https://github.com/docker/build-push-action/compare/v5...v6)
---
updated-dependencies:
- dependency-name: docker/build-push-action
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/deploy-dockerhub.yml | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/.github/workflows/deploy-dockerhub.yml b/.github/workflows/deploy-dockerhub.yml
index a565ca8779..3559ae754e 100644
--- a/.github/workflows/deploy-dockerhub.yml
+++ b/.github/workflows/deploy-dockerhub.yml
@@ -27,7 +27,7 @@ jobs:
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Deploy Main
if: github.ref == 'refs/heads/main'
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
push: true
tags: safeglobal/safe-wallet-web:staging
@@ -38,7 +38,7 @@ jobs:
cache-to: type=gha,mode=max
- name: Deploy Develop
if: github.ref == 'refs/heads/dev'
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
push: true
tags: safeglobal/safe-wallet-web:dev
@@ -49,7 +49,7 @@ jobs:
cache-to: type=gha,mode=max
- name: Deploy Tag
if: (github.event_name == 'release' && github.event.action == 'released')
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
push: true
tags: |
From 9ccabe35b14a8a7f7e0b9fae1f1c8885b3a40350 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:11:27 +0200
Subject: [PATCH 27/81] Chore(deps): Bump contributor-assistant/github-action
(#4097)
Bumps [contributor-assistant/github-action](https://github.com/contributor-assistant/github-action) from 2.2.0 to 2.5.1.
- [Release notes](https://github.com/contributor-assistant/github-action/releases)
- [Commits](https://github.com/contributor-assistant/github-action/compare/v2.2.0...v2.5.1)
---
updated-dependencies:
- dependency-name: contributor-assistant/github-action
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/cla.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml
index 26ffce42c4..e7d985b475 100644
--- a/.github/workflows/cla.yml
+++ b/.github/workflows/cla.yml
@@ -13,7 +13,7 @@ jobs:
- name: 'CLA Assistant'
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
# Beta Release
- uses: contributor-assistant/github-action@v2.2.0
+ uses: contributor-assistant/github-action@v2.5.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# the below token should have repo scope and must be manually added by you in the repository's secret
From 8bf57b95d5b06da295909d0f56cca293de4492fd Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:11:33 +0200
Subject: [PATCH 28/81] Chore(deps): Bump softprops/action-gh-release from 1 to
2 (#4099)
Bumps [softprops/action-gh-release](https://github.com/softprops/action-gh-release) from 1 to 2.
- [Release notes](https://github.com/softprops/action-gh-release/releases)
- [Changelog](https://github.com/softprops/action-gh-release/blob/master/CHANGELOG.md)
- [Commits](https://github.com/softprops/action-gh-release/compare/v1...v2)
---
updated-dependencies:
- dependency-name: softprops/action-gh-release
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/tag-release.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/tag-release.yml b/.github/workflows/tag-release.yml
index 3821d33edd..d389a52869 100644
--- a/.github/workflows/tag-release.yml
+++ b/.github/workflows/tag-release.yml
@@ -28,7 +28,7 @@ jobs:
- name: GitHub release
if: steps.version.outputs.version
- uses: softprops/action-gh-release@v1
+ uses: softprops/action-gh-release@v2
id: create_release
with:
draft: true
From 3bff12074cf1c858d9cf4fd800f465c479178394 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:11:42 +0200
Subject: [PATCH 29/81] Chore(deps): Bump actions/upload-artifact from 3 to 4
(#4098)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)
---
updated-dependencies:
- dependency-name: actions/upload-artifact
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/nextjs-bundle-analysis.yml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.github/workflows/nextjs-bundle-analysis.yml b/.github/workflows/nextjs-bundle-analysis.yml
index 1e3ad27f29..49d08b0097 100644
--- a/.github/workflows/nextjs-bundle-analysis.yml
+++ b/.github/workflows/nextjs-bundle-analysis.yml
@@ -32,7 +32,7 @@ jobs:
run: npx -p nextjs-bundle-analysis report
- name: Upload bundle
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
name: bundle
path: .next/analyze/__bundle_analysis.json
From 6d0e159a81f589466adccbf582e721ea70610df3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:12:22 +0200
Subject: [PATCH 30/81] Chore(deps): Bump @web3-onboard/injected-wallets from
2.10.14 to 2.11.2 (#4100)
Bumps [@web3-onboard/injected-wallets](https://github.com/blocknative/web3-onboard/tree/HEAD/packages/injected) from 2.10.14 to 2.11.2.
- [Release notes](https://github.com/blocknative/web3-onboard/releases)
- [Commits](https://github.com/blocknative/web3-onboard/commits/HEAD/packages/injected)
---
updated-dependencies:
- dependency-name: "@web3-onboard/injected-wallets"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 37 +++++++++++++++++++++++++------------
2 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/package.json b/package.json
index 2904ab1250..ac4c9330b8 100644
--- a/package.json
+++ b/package.json
@@ -66,7 +66,7 @@
"@walletconnect/web3wallet": "^1.12.1",
"@web3-onboard/coinbase": "^2.2.6",
"@web3-onboard/core": "^2.21.4",
- "@web3-onboard/injected-wallets": "^2.10.14",
+ "@web3-onboard/injected-wallets": "^2.11.2",
"@web3-onboard/keystone": "^2.3.7",
"@web3-onboard/ledger": "2.3.2",
"@web3-onboard/trezor": "^2.4.2",
diff --git a/yarn.lock b/yarn.lock
index a6e4dbd650..9732294342 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6840,14 +6840,13 @@
"@coinbase/wallet-sdk" "^3.7.2"
"@web3-onboard/common" "^2.3.3"
-"@web3-onboard/common@^2.2.3", "@web3-onboard/common@^2.3.3", "@web3-onboard/common@^2.3.4":
- version "2.3.4"
- resolved "https://registry.yarnpkg.com/@web3-onboard/common/-/common-2.3.4.tgz#1ce41e090c19e8ac802c45737de3dda3dabea751"
- integrity sha512-LQM7ZA1LoJ4GirsVEWHkv9KNJcrIT+AplR957BP5O8tll+p/A1GCju89C7jAMnb3+9LShUCwHcbE4o8l8gVb9A==
+"@web3-onboard/common@^2.2.3", "@web3-onboard/common@^2.3.3", "@web3-onboard/common@^2.3.4", "@web3-onboard/common@^2.4.1":
+ version "2.4.2"
+ resolved "https://registry.yarnpkg.com/@web3-onboard/common/-/common-2.4.2.tgz#ffa7b1a7cb6410d9cc4d7b38d50b97a857b334cb"
+ integrity sha512-3+zkBru5W2jBYFBPPQsnqZ7tuN1GUyM5PzD9/MmhvjCLNhmjFtMQ0MkLzG4Yshodb4UW/DmZpjUVrpjdhEhj/Q==
dependencies:
- bignumber.js "^9.1.0"
- ethers "5.5.4"
joi "17.9.1"
+ viem "2.12.0"
"@web3-onboard/core@^2.21.4":
version "2.21.4"
@@ -6879,12 +6878,12 @@
joi "17.9.1"
rxjs "^7.5.2"
-"@web3-onboard/injected-wallets@^2.10.14":
- version "2.10.14"
- resolved "https://registry.yarnpkg.com/@web3-onboard/injected-wallets/-/injected-wallets-2.10.14.tgz#ad4f7585927651050caec232a62774f422fb9c01"
- integrity sha512-lU/YCCYNr7+Qgg1lJ1vQofmJhMPZrkRTYO0lgkGsmLFVWZZ4rJIU1dm31h5iHm4nVUbw3ItYDICKsI1NgX46AQ==
+"@web3-onboard/injected-wallets@^2.11.2":
+ version "2.11.2"
+ resolved "https://registry.yarnpkg.com/@web3-onboard/injected-wallets/-/injected-wallets-2.11.2.tgz#f39c937f903875cfaad6373e1975dde2660d9e17"
+ integrity sha512-VeI0LTFKAcikBLBOub/avzdvc2SWOh3qLjqw/Yh34YS7ArGG5jrQXSbOuVXLqQoW07TyY4SDHXTI1Yft9MiF4Q==
dependencies:
- "@web3-onboard/common" "^2.3.3"
+ "@web3-onboard/common" "^2.4.1"
joi "17.9.1"
lodash.uniqby "^4.7.0"
@@ -7835,7 +7834,7 @@ bigint-buffer@^1.1.5:
dependencies:
bindings "^1.3.0"
-bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.1.0, bignumber.js@^9.1.1, bignumber.js@^9.1.2:
+bignumber.js@^9.0.0, bignumber.js@^9.0.1, bignumber.js@^9.1.1, bignumber.js@^9.1.2:
version "9.1.2"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.2.tgz#b7c4242259c008903b13707983b5f4bbd31eda0c"
integrity sha512-2/mKyZH9K85bzOEfhXDBFZTGd1CTs+5IHpeFQo9luiBG7hghdC851Pj2WAhb6E3R6b9tZj/XKhbg4fum+Kepug==
@@ -17930,6 +17929,20 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
+viem@2.12.0:
+ version "2.12.0"
+ resolved "https://registry.yarnpkg.com/viem/-/viem-2.12.0.tgz#699ba326a1ce0df81042dc8b6f22fa751f9cefce"
+ integrity sha512-XBvORspE4x2/gfy7idH6IVFwkJiXirygFCU3lxUH6fttsj8zufLtgiokfvZF/LAZUEDvdxSgL08whSYgffM2fw==
+ dependencies:
+ "@adraffy/ens-normalize" "1.10.0"
+ "@noble/curves" "1.2.0"
+ "@noble/hashes" "1.3.2"
+ "@scure/bip32" "1.3.2"
+ "@scure/bip39" "1.2.1"
+ abitype "1.0.0"
+ isows "1.0.4"
+ ws "8.13.0"
+
viem@^2.1.1:
version "2.13.8"
resolved "https://registry.yarnpkg.com/viem/-/viem-2.13.8.tgz#d6aaeecc84e5ee5cac1566f103ed4cf0335ef811"
From b8894e2d58eeeb6bccf9a76f4d70ced05fc5e419 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 23 Aug 2024 10:12:35 +0200
Subject: [PATCH 31/81] Chore(deps-dev): Bump @types/js-cookie from 3.0.4 to
3.0.6 (#4101)
Bumps [@types/js-cookie](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/js-cookie) from 3.0.4 to 3.0.6.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/js-cookie)
---
updated-dependencies:
- dependency-name: "@types/js-cookie"
dependency-type: direct:development
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index ac4c9330b8..dd97051aa0 100644
--- a/package.json
+++ b/package.json
@@ -119,7 +119,7 @@
"@testing-library/user-event": "^14.4.2",
"@typechain/ethers-v6": "^0.5.1",
"@types/jest": "^29.5.4",
- "@types/js-cookie": "^3.0.2",
+ "@types/js-cookie": "^3.0.6",
"@types/lodash": "^4.14.182",
"@types/node": "18.11.18",
"@types/qrcode": "^1.5.5",
diff --git a/yarn.lock b/yarn.lock
index 9732294342..f2950ff6b1 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5828,10 +5828,10 @@
expect "^29.0.0"
pretty-format "^29.0.0"
-"@types/js-cookie@^3.0.2":
- version "3.0.4"
- resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-3.0.4.tgz#23475b6d3b03acc84192e7c24da88eb38c1039ef"
- integrity sha512-vMMnFF+H5KYqdd/myCzq6wLDlPpteJK+jGFgBus3Da7lw+YsDmx2C8feGTzY2M3Fo823yON+HC2CL240j4OV+w==
+"@types/js-cookie@^3.0.6":
+ version "3.0.6"
+ resolved "https://registry.yarnpkg.com/@types/js-cookie/-/js-cookie-3.0.6.tgz#a04ca19e877687bd449f5ad37d33b104b71fdf95"
+ integrity sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==
"@types/jsdom@^20.0.0":
version "20.0.1"
From 14c62e4475fb2b98fd565c7aecb0a3908cac196e Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Mon, 26 Aug 2024 11:09:28 +0200
Subject: [PATCH 32/81] Fix: test wallet types
---
src/services/private-key-module/index.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/src/services/private-key-module/index.ts b/src/services/private-key-module/index.ts
index 550346265d..f8c6dd78da 100644
--- a/src/services/private-key-module/index.ts
+++ b/src/services/private-key-module/index.ts
@@ -87,8 +87,9 @@ const PrivateKeyModule = (chainId: ChainInfo['chainId'], rpcUri: ChainInfo['rpcU
// @ts-ignore
eth_getCode: async ({ params }) => provider.getCode(params[0], params[1]),
-
+ // @ts-ignore
eth_accounts: async () => [wallet.address],
+ // @ts-ignore
eth_requestAccounts: async () => [wallet.address],
eth_call: async ({ params }: { params: any }) => wallet.call(params[0]),
From 706f1d357a99e624038c62d36041ae18d18140d3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 26 Aug 2024 13:28:15 +0200
Subject: [PATCH 33/81] Chore(deps): Bump @emotion/cache from 11.11.0 to
11.13.1 (#4111)
Bumps [@emotion/cache](https://github.com/emotion-js/emotion) from 11.11.0 to 11.13.1.
- [Release notes](https://github.com/emotion-js/emotion/releases)
- [Changelog](https://github.com/emotion-js/emotion/blob/main/CHANGELOG.md)
- [Commits](https://github.com/emotion-js/emotion/compare/@emotion/cache@11.11.0...@emotion/cache@11.13.1)
---
updated-dependencies:
- dependency-name: "@emotion/cache"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 44 +++++++++++++++++++++++++++-----------------
2 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/package.json b/package.json
index dd97051aa0..754a7ab095 100644
--- a/package.json
+++ b/package.json
@@ -45,7 +45,7 @@
"dependencies": {
"@cowprotocol/widget-react": "^0.9.3",
"@ducanh2912/next-pwa": "^9.7.1",
- "@emotion/cache": "^11.11.0",
+ "@emotion/cache": "^11.13.1",
"@emotion/react": "^11.11.0",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0",
diff --git a/yarn.lock b/yarn.lock
index f2950ff6b1..9a30452ab3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1332,15 +1332,15 @@
source-map "^0.5.7"
stylis "4.2.0"
-"@emotion/cache@^11.11.0":
- version "11.11.0"
- resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.11.0.tgz#809b33ee6b1cb1a625fef7a45bc568ccd9b8f3ff"
- integrity sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==
- dependencies:
- "@emotion/memoize" "^0.8.1"
- "@emotion/sheet" "^1.2.2"
- "@emotion/utils" "^1.2.1"
- "@emotion/weak-memoize" "^0.3.1"
+"@emotion/cache@^11.11.0", "@emotion/cache@^11.13.1":
+ version "11.13.1"
+ resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7"
+ integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==
+ dependencies:
+ "@emotion/memoize" "^0.9.0"
+ "@emotion/sheet" "^1.4.0"
+ "@emotion/utils" "^1.4.0"
+ "@emotion/weak-memoize" "^0.4.0"
stylis "4.2.0"
"@emotion/hash@^0.9.1":
@@ -1360,6 +1360,11 @@
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
+"@emotion/memoize@^0.9.0":
+ version "0.9.0"
+ resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102"
+ integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
+
"@emotion/react@^11.11.0":
version "11.11.1"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.11.1.tgz#b2c36afac95b184f73b08da8c214fdf861fa4157"
@@ -1395,10 +1400,10 @@
multipipe "^1.0.2"
through "^2.3.8"
-"@emotion/sheet@^1.2.2":
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.2.2.tgz#d58e788ee27267a14342303e1abb3d508b6d0fec"
- integrity sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==
+"@emotion/sheet@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c"
+ integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
"@emotion/styled@^11.11.0":
version "11.11.0"
@@ -1422,16 +1427,21 @@
resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963"
integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==
-"@emotion/utils@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.2.1.tgz#bbab58465738d31ae4cb3dbb6fc00a5991f755e4"
- integrity sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==
+"@emotion/utils@^1.2.1", "@emotion/utils@^1.4.0":
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.0.tgz#262f1d02aaedb2ec91c83a0955dd47822ad5fbdd"
+ integrity sha512-spEnrA1b6hDR/C68lC2M7m6ALPUHZC0lIY7jAS/B/9DuuO1ZP04eov8SMv/6fwRd8pzmsn2AuJEznRREWlQrlQ==
"@emotion/weak-memoize@^0.3.1":
version "0.3.1"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.3.1.tgz#d0fce5d07b0620caa282b5131c297bb60f9d87e6"
integrity sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==
+"@emotion/weak-memoize@^0.4.0":
+ version "0.4.0"
+ resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6"
+ integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
+
"@esbuild/aix-ppc64@0.20.2":
version "0.20.2"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537"
From b6e9a0239e1af02bc719d719934631489976c753 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 26 Aug 2024 13:28:28 +0200
Subject: [PATCH 34/81] Chore(deps): Bump react and @types/react (#4109)
Bumps [react](https://github.com/facebook/react/tree/HEAD/packages/react) and [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react). These dependencies needed to be updated together.
Updates `react` from 18.2.0 to 18.3.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v18.3.1/packages/react)
Updates `@types/react` from 18.2.75 to 18.3.4
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react)
---
updated-dependencies:
- dependency-name: react
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name: "@types/react"
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 4 ++--
yarn.lock | 16 ++++++++--------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/package.json b/package.json
index 754a7ab095..3c9c244819 100644
--- a/package.json
+++ b/package.json
@@ -84,7 +84,7 @@
"next": "^14.1.1",
"papaparse": "^5.3.2",
"qrcode.react": "^3.1.0",
- "react": "^18.2.0",
+ "react": "^18.3.1",
"react-dom": "^18.2.0",
"react-dropzone": "^14.2.3",
"react-gtm-module": "^2.0.11",
@@ -123,7 +123,7 @@
"@types/lodash": "^4.14.182",
"@types/node": "18.11.18",
"@types/qrcode": "^1.5.5",
- "@types/react": "^18.2.75",
+ "@types/react": "^18.3.4",
"@types/react-dom": "^18.2.24",
"@types/react-gtm-module": "^2.0.3",
"@types/semver": "^7.3.10",
diff --git a/yarn.lock b/yarn.lock
index 9a30452ab3..d4372c867d 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6020,10 +6020,10 @@
dependencies:
"@types/react" "*"
-"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.2.75":
- version "18.2.75"
- resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.75.tgz#45d18f384939306d35312def1bf532eb38a68562"
- integrity sha512-+DNnF7yc5y0bHkBTiLKqXFe+L4B3nvOphiMY3tuA5X10esmjqk7smyBZzbGTy2vsiy/Bnzj8yFIBL8xhRacoOg==
+"@types/react@*", "@types/react@^16.8.0 || ^17.0.0 || ^18.0.0", "@types/react@^18.3.4":
+ version "18.3.4"
+ resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.4.tgz#dfdd534a1d081307144c00e325c06e00312c93a3"
+ integrity sha512-J7W30FTdfCxDDjmfRM+/JqLHBIyl7xUIp9kwK637FGmY7+mkSFSe6L4jpZzhj5QMfLssSDP4/i75AKkrdC7/Jw==
dependencies:
"@types/prop-types" "*"
csstype "^3.0.2"
@@ -15461,10 +15461,10 @@ react@16.13.1:
object-assign "^4.1.1"
prop-types "^15.6.2"
-"react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.2.0:
- version "18.2.0"
- resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
- integrity sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==
+"react@^16.8.0 || ^17.0.0 || ^18.0.0", react@^18.3.1:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
+ integrity sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==
dependencies:
loose-envify "^1.1.0"
From 04f940e95568f5f7c76258fd4bed491eb4ededd4 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 26 Aug 2024 13:28:39 +0200
Subject: [PATCH 35/81] Chore(deps): Bump aws-actions/configure-aws-credentials
from 3 to 4 (#4106)
Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 3 to 4.
- [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases)
- [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md)
- [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/v3...v4)
---
updated-dependencies:
- dependency-name: aws-actions/configure-aws-credentials
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
.github/workflows/deploy-dev.yml | 2 +-
.github/workflows/deploy-production.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml
index aa64e261a4..e6ef646e00 100644
--- a/.github/workflows/deploy-dev.yml
+++ b/.github/workflows/deploy-dev.yml
@@ -46,7 +46,7 @@ jobs:
#- uses: ./.github/workflows/build-storybook
- name: Configure AWS credentials
- uses: aws-actions/configure-aws-credentials@v3
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE }}
aws-region: ${{ secrets.AWS_REGION }}
diff --git a/.github/workflows/deploy-production.yml b/.github/workflows/deploy-production.yml
index 84a0e6ba61..32a2f2ff64 100644
--- a/.github/workflows/deploy-production.yml
+++ b/.github/workflows/deploy-production.yml
@@ -33,7 +33,7 @@ jobs:
run: sha256sum "$ARCHIVE_NAME".tar.gz > ${{ env.ARCHIVE_NAME }}-sha256-checksum.txt
- name: Configure AWS credentials
- uses: aws-actions/configure-aws-credentials@v3
+ uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE }}
aws-region: ${{ secrets.AWS_REGION }}
From 0ff5bd91f8f595a83a5559776b689582dbe44384 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Mon, 26 Aug 2024 21:56:45 +0200
Subject: [PATCH 36/81] Fix: don't show "verified by WalletConnect" (#4112)
---
.../WcProposalForm/ProposalVerification.tsx | 54 +++++--------------
1 file changed, 12 insertions(+), 42 deletions(-)
diff --git a/src/features/walletconnect/components/WcProposalForm/ProposalVerification.tsx b/src/features/walletconnect/components/WcProposalForm/ProposalVerification.tsx
index 15b7a37d60..869c10bcbf 100644
--- a/src/features/walletconnect/components/WcProposalForm/ProposalVerification.tsx
+++ b/src/features/walletconnect/components/WcProposalForm/ProposalVerification.tsx
@@ -1,72 +1,42 @@
import type { Web3WalletTypes } from '@walletconnect/web3wallet'
import { Alert, SvgIcon } from '@mui/material'
-import type { AlertColor } from '@mui/material'
import AlertIcon from '@/public/images/notifications/alert.svg'
-import type { Verify } from '@walletconnect/types'
-import type { ComponentType, ReactElement } from 'react'
-import CloseIcon from '@/public/images/common/close.svg'
-import InfoIcon from '@/public/images/notifications/info.svg'
-import CheckIcon from '@/public/images/common/check.svg'
+import type { ReactElement } from 'react'
import { getPeerName } from '@/features/walletconnect/services/utils'
import css from './styles.module.css'
-const Validation: {
- [key in Verify.Context['verified']['validation']]: {
- color: AlertColor
- desc: string
- Icon: ComponentType
- }
-} = {
- VALID: {
- color: 'success',
- desc: 'has been verified by WalletConnect.',
- Icon: CheckIcon,
- },
- UNKNOWN: {
- color: 'warning',
- desc: 'has not been verified by WalletConnect.',
- Icon: InfoIcon,
- },
- INVALID: {
- color: 'error',
- desc: 'has a domain that does not match the sender of this request. Approving it may result in a loss of funds.',
- Icon: CloseIcon,
- },
-}
-
const ProposalVerification = ({ proposal }: { proposal: Web3WalletTypes.SessionProposal }): ReactElement | null => {
- const { proposer } = proposal.params
const { isScam, validation } = proposal.verifyContext.verified
- if (validation === 'UNKNOWN') {
+ if (validation === 'UNKNOWN' || validation === 'VALID') {
return null
}
- const _validation = Validation[validation]
- const color = isScam ? 'error' : _validation.color
- const Icon = isScam ? AlertIcon : _validation.Icon
+ const appName = getPeerName(proposal.params.proposer)
return (
palette[color].background }}
+ severity="error"
+ sx={{ bgcolor: 'error.background' }}
className={css.alert}
icon={
palette[color].main,
+ fill: 'error.main',
},
}}
/>
}
>
{isScam
- ? `We prevent connecting to ${getPeerName(proposer) || 'this dApp'} as they are a known scam.`
- : `${getPeerName(proposer) || 'This dApp'} ${_validation.desc}`}
+ ? `We prevent connecting to ${appName || 'this dApp'} as they are a known scam.`
+ : `${
+ appName || 'This dApp'
+ } has a domain that does not match the sender of this request. Approving it may result in a loss of funds.`}
)
}
From 695b5ed1af8a9a20620dc3913523404400ca10bf Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Tue, 27 Aug 2024 10:12:25 +0200
Subject: [PATCH 37/81] 1.41.4
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 3c9c244819..9bae0ee87c 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.41.3",
+ "version": "1.41.4",
"type": "module",
"scripts": {
"dev": "next dev",
From e072800dd9c0d428f22da7561589bfa1a1771b5f Mon Sep 17 00:00:00 2001
From: LeafBreezes
Date: Tue, 27 Aug 2024 22:45:05 +0800
Subject: [PATCH 38/81] Tests: add formatNumber test case (#4117)
(Github spam bot)
---
src/utils/__tests__/formatNumber.test.ts | 34 +++++++++++++++++++++++-
1 file changed, 33 insertions(+), 1 deletion(-)
diff --git a/src/utils/__tests__/formatNumber.test.ts b/src/utils/__tests__/formatNumber.test.ts
index baaa2cbee0..d222a0e5bc 100644
--- a/src/utils/__tests__/formatNumber.test.ts
+++ b/src/utils/__tests__/formatNumber.test.ts
@@ -1,4 +1,4 @@
-import { formatAmountPrecise, formatAmount, formatCurrency } from '@/utils/formatNumber'
+import { formatAmountPrecise, formatAmount, formatCurrency, formatCurrencyPrecise } from '@/utils/formatNumber'
describe('formatNumber', () => {
describe('formatAmountPrecise', () => {
@@ -58,4 +58,36 @@ describe('formatNumber', () => {
expect(formatCurrency(1234.12, 'USD', 4)).toBe('$ 1.23K')
})
})
+
+ describe('formatCurrencyPrecise', () => {
+ it('should format the number correctly for USD', () => {
+ const result = formatCurrencyPrecise(1234.56, 'USD')
+ expect(result).toBe('$ 1,234.56')
+ })
+
+ it('should format the number correctly for EUR', () => {
+ const result = formatCurrencyPrecise(1234.56, 'EUR')
+ expect(result).toBe('€ 1,234.56')
+ })
+
+ it('should handle string input as number', () => {
+ const result = formatCurrencyPrecise('1234.56', 'USD')
+ expect(result).toBe('$ 1,234.56')
+ })
+
+ it('should add the narrow non-breaking space after the currency symbol', () => {
+ const result = formatCurrencyPrecise(1234.56, 'USD')
+ expect(result).toBe('$ 1,234.56')
+ })
+
+ it('should format the number correctly with 5 decimal places for USD', () => {
+ const result = formatCurrencyPrecise(1234.56789, 'USD')
+ expect(result).toBe('$ 1,234.57')
+ })
+
+ it('should return "NaN" for invalid number input', () => {
+ const result = formatCurrencyPrecise('invalid-number', 'USD')
+ expect(result).toBe('$NaN ')
+ })
+ })
})
From 6c89ee27b3805ee8596ea3d3dc841476e7becd0b Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Tue, 27 Aug 2024 19:58:29 +0200
Subject: [PATCH 39/81] Chore: upgrade protocol-kit (#4118)
* Chore: upgrade protocol-kit
* Fix types
---
package.json | 2 +-
src/services/tx/tx-sender/create.ts | 1 +
yarn.lock | 57 +++++++++++++++--------------
3 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/package.json b/package.json
index 9bae0ee87c..45d338895c 100644
--- a/package.json
+++ b/package.json
@@ -55,7 +55,7 @@
"@mui/x-date-pickers": "^5.0.20",
"@reduxjs/toolkit": "^2.2.6",
"@safe-global/api-kit": "^2.4.4",
- "@safe-global/protocol-kit": "^4.0.4",
+ "@safe-global/protocol-kit": "^4.1.0",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-deployments": "^1.37.3",
"@safe-global/safe-gateway-typescript-sdk": "3.22.1",
diff --git a/src/services/tx/tx-sender/create.ts b/src/services/tx/tx-sender/create.ts
index 64759e637e..4d348a0356 100644
--- a/src/services/tx/tx-sender/create.ts
+++ b/src/services/tx/tx-sender/create.ts
@@ -66,6 +66,7 @@ export const createSwapOwnerTx = async (
const safeVersion = await safeSDK.getContractVersion()
const contract = await getReadOnlyGnosisSafeContract(chain, safeVersion)
+ // @ts-ignore SwapOwnerTxParams is a union type and the method expects a specific one
const data = contract.encode('swapOwner', [SENTINEL_ADDRESS, txParams.oldOwnerAddress, txParams.newOwnerAddress])
const tx = {
diff --git a/yarn.lock b/yarn.lock
index d4372c867d..d48d950af0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4133,6 +4133,20 @@
ethers "^6.13.1"
semver "^7.6.2"
+"@safe-global/protocol-kit@^4.1.0":
+ version "4.1.0"
+ resolved "https://registry.yarnpkg.com/@safe-global/protocol-kit/-/protocol-kit-4.1.0.tgz#8ab41e179c559840f0cd6b6ae296438dabe1793f"
+ integrity sha512-WAGXEn6UvKGlEYNqcWUasLZ4240sVWBg8T2SsfHoTs8Im0x2i48CNNZ5Mw9x+oKqhWs/Q9frNG6JcycN19LDRw==
+ dependencies:
+ "@noble/hashes" "^1.3.3"
+ "@safe-global/safe-core-sdk-types" "^5.1.0"
+ "@safe-global/safe-deployments" "^1.37.3"
+ "@safe-global/safe-modules-deployments" "^2.2.1"
+ abitype "^1.0.2"
+ ethereumjs-util "^7.1.5"
+ ethers "^6.13.1"
+ semver "^7.6.2"
+
"@safe-global/safe-apps-sdk@^9.1.0":
version "9.1.0"
resolved "https://registry.yarnpkg.com/@safe-global/safe-apps-sdk/-/safe-apps-sdk-9.1.0.tgz#0e65913e0f202e529ed3c846e0f5a98c2d35aa98"
@@ -4155,6 +4169,13 @@
dependencies:
abitype "^1.0.2"
+"@safe-global/safe-core-sdk-types@^5.1.0":
+ version "5.1.0"
+ resolved "https://registry.yarnpkg.com/@safe-global/safe-core-sdk-types/-/safe-core-sdk-types-5.1.0.tgz#af8d877b9af231242d023c7182f78ff4223bc3f4"
+ integrity sha512-UzXR4zWmVzux25FcIm4H049QhZZpVpIBL5HE+V0p5gHpArZROL+t24fZmsKUf403CtBxIJM5zZSVQL0nFJi+IQ==
+ dependencies:
+ abitype "^1.0.2"
+
"@safe-global/safe-deployments@^1.37.3":
version "1.37.3"
resolved "https://registry.yarnpkg.com/@safe-global/safe-deployments/-/safe-deployments-1.37.3.tgz#ded9fa6bb04f0e8972c00c481badcf513d590b0b"
@@ -4177,6 +4198,11 @@
resolved "https://registry.yarnpkg.com/@safe-global/safe-modules-deployments/-/safe-modules-deployments-1.2.0.tgz#ca871c3f553cd16cbea1aac8f8be16498329a7d3"
integrity sha512-/pjHIPaYwGRM5oOB7lc+yf28fWEq7twNP5dJxpLFgG/9UR4E3F+XfFdYkpP22eIvmOkBwCJXJZfPfESh9WSF2w==
+"@safe-global/safe-modules-deployments@^2.2.1":
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/@safe-global/safe-modules-deployments/-/safe-modules-deployments-2.2.1.tgz#a8b88f2afc6ec04fed09968fe1e4990ed975c86e"
+ integrity sha512-H0XpusyXVcsTuRsQSq0FoBKqRfhZH87/1DrFEmXXPXmI3fJkvxq3KpTaTTqzcqoIe/J+erwVZQUYNfL68EcvAQ==
+
"@scure/base@~1.1.0":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f"
@@ -16646,16 +16672,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16743,14 +16760,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", 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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18435,7 +18445,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18453,15 +18463,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From d4f4d6dd0330a6351e4e5d7b060dd2d06b386326 Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Tue, 27 Aug 2024 20:03:05 +0200
Subject: [PATCH 40/81] 1.41.5
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index 45d338895c..05376d0080 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.41.4",
+ "version": "1.41.5",
"type": "module",
"scripts": {
"dev": "next dev",
From f3cdeb2a76fa021b6bdd61c53277dfae2b68f6e7 Mon Sep 17 00:00:00 2001
From: Shaik-Sirajuddin <89742297+Shaik-Sirajuddin@users.noreply.github.com>
Date: Wed, 28 Aug 2024 20:49:45 +0530
Subject: [PATCH 41/81] fix: inconsistent layout in dashboard pending
transactions view (#4034)
* fix: alignment in transactions view dashboard
* feat: apply truncate text default
---
.../PendingTxs/PendingTxListItem.tsx | 20 +++++++++++--------
.../dashboard/PendingTxs/styles.module.css | 20 +++++++++++++++++--
src/components/transactions/TxInfo/index.tsx | 13 ++++++------
.../transactions/TxInfo/styles.module.css | 5 +++++
.../swap/components/SwapTxInfo/SwapTx.tsx | 10 +++++++++-
5 files changed, 51 insertions(+), 17 deletions(-)
create mode 100644 src/components/transactions/TxInfo/styles.module.css
diff --git a/src/components/dashboard/PendingTxs/PendingTxListItem.tsx b/src/components/dashboard/PendingTxs/PendingTxListItem.tsx
index f58b651db5..ab409da7d0 100644
--- a/src/components/dashboard/PendingTxs/PendingTxListItem.tsx
+++ b/src/components/dashboard/PendingTxs/PendingTxListItem.tsx
@@ -36,17 +36,21 @@ const PendingTx = ({ transaction }: PendingTxType): ReactElement => {
return (
- {isMultisigExecutionInfo(transaction.executionInfo) && transaction.executionInfo.nonce}
+
+
+ {isMultisigExecutionInfo(transaction.executionInfo) && transaction.executionInfo.nonce}
+
-
-
-
-
-
+
+
+
-
+
+
+
+
-
+
{isMultisigExecutionInfo(transaction.executionInfo) && (
{
- return <>{info.methodName}>
+ return {info.methodName}
}
const CreationTx = ({ info }: { info: Creation }): ReactElement => {
- return <>Created by {shortenAddress(info.creator.value)}>
+ return Created by {shortenAddress(info.creator.value)}
}
const MultiSendTx = ({ info }: { info: MultiSend }): ReactElement => {
return (
- <>
+
{info.actionCount} {`action${info.actionCount > 1 ? 's' : ''}`}
- >
+
)
}
@@ -105,9 +107,8 @@ const SettingsChangeTx = ({ info }: { info: SettingsChange }): ReactElement => {
info.settingsInfo?.type === SettingsInfoType.ENABLE_MODULE ||
info.settingsInfo?.type === SettingsInfoType.DISABLE_MODULE
) {
- return <>{info.settingsInfo.module.name}>
+ return {info.settingsInfo.module.name}
}
-
return <>>
}
diff --git a/src/components/transactions/TxInfo/styles.module.css b/src/components/transactions/TxInfo/styles.module.css
new file mode 100644
index 0000000000..5e6635d9b5
--- /dev/null
+++ b/src/components/transactions/TxInfo/styles.module.css
@@ -0,0 +1,5 @@
+.txInfo {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
diff --git a/src/features/swap/components/SwapTxInfo/SwapTx.tsx b/src/features/swap/components/SwapTxInfo/SwapTx.tsx
index c432fab029..c06651486e 100644
--- a/src/features/swap/components/SwapTxInfo/SwapTx.tsx
+++ b/src/features/swap/components/SwapTxInfo/SwapTx.tsx
@@ -33,7 +33,15 @@ export const SwapTx = ({ info }: { info: Order }): ReactElement => {
}
return (
-
+
{from}
to
From d834e2285bdce42d5cb0c1a23e37d0ad33c6bde5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 2 Sep 2024 11:28:10 +0200
Subject: [PATCH 42/81] Chore(deps): Bump react-dom and @types/react-dom
(#4128)
Bumps [react-dom](https://github.com/facebook/react/tree/HEAD/packages/react-dom) and [@types/react-dom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react-dom). These dependencies needed to be updated together.
Updates `react-dom` from 18.2.0 to 18.3.1
- [Release notes](https://github.com/facebook/react/releases)
- [Changelog](https://github.com/facebook/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/facebook/react/commits/v18.3.1/packages/react-dom)
Updates `@types/react-dom` from 18.2.24 to 18.3.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react-dom)
---
updated-dependencies:
- dependency-name: react-dom
dependency-type: direct:production
update-type: version-update:semver-minor
- dependency-name: "@types/react-dom"
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 4 ++--
yarn.lock | 57 +++++++++++++++++++++++++++++++++++++---------------
2 files changed, 43 insertions(+), 18 deletions(-)
diff --git a/package.json b/package.json
index 05376d0080..55d13e0af4 100644
--- a/package.json
+++ b/package.json
@@ -85,7 +85,7 @@
"papaparse": "^5.3.2",
"qrcode.react": "^3.1.0",
"react": "^18.3.1",
- "react-dom": "^18.2.0",
+ "react-dom": "^18.3.1",
"react-dropzone": "^14.2.3",
"react-gtm-module": "^2.0.11",
"react-hook-form": "7.41.1",
@@ -124,7 +124,7 @@
"@types/node": "18.11.18",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.4",
- "@types/react-dom": "^18.2.24",
+ "@types/react-dom": "^18.3.0",
"@types/react-gtm-module": "^2.0.3",
"@types/semver": "^7.3.10",
"@typescript-eslint/eslint-plugin": "^7.6.0",
diff --git a/yarn.lock b/yarn.lock
index d48d950af0..959d373c63 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6027,10 +6027,10 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
-"@types/react-dom@^18.0.0", "@types/react-dom@^18.2.24":
- version "18.2.24"
- resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.24.tgz#8dda8f449ae436a7a6e91efed8035d4ab03ff759"
- integrity sha512-cN6upcKd8zkGy4HU9F1+/s98Hrp6D4MOcippK4PoE8OZRngohHZpbJn1GsaDLz87MqvHNoT13nHvNqM9ocRHZg==
+"@types/react-dom@^18.0.0", "@types/react-dom@^18.3.0":
+ version "18.3.0"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.0.tgz#0cbc818755d87066ab6ca74fbedb2547d74a82b0"
+ integrity sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==
dependencies:
"@types/react" "*"
@@ -15358,13 +15358,13 @@ react-dom@16.13.1:
prop-types "^15.6.2"
scheduler "^0.19.1"
-"react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", react-dom@^18.2.0:
- version "18.2.0"
- resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.2.0.tgz#22aaf38708db2674ed9ada224ca4aa708d821e3d"
- integrity sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==
+"react-dom@^16.8.0 || ^17.0.0 || ^18.0.0", react-dom@^18.3.1:
+ version "18.3.1"
+ resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
+ integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
dependencies:
loose-envify "^1.1.0"
- scheduler "^0.23.0"
+ scheduler "^0.23.2"
react-dom@^17.0.2:
version "17.0.2"
@@ -16122,10 +16122,10 @@ scheduler@^0.20.2:
loose-envify "^1.1.0"
object-assign "^4.1.1"
-scheduler@^0.23.0:
- version "0.23.0"
- resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.0.tgz#ba8041afc3d30eb206a487b6b384002e4e61fdfe"
- integrity sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==
+scheduler@^0.23.2:
+ version "0.23.2"
+ resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
+ integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
dependencies:
loose-envify "^1.1.0"
@@ -16672,7 +16672,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16760,7 +16769,14 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18445,7 +18461,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18463,6 +18479,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From c209e2d4227aac953ea49f03377e160dce40b2b3 Mon Sep 17 00:00:00 2001
From: Usame Algan <5880855+usame-algan@users.noreply.github.com>
Date: Tue, 3 Sep 2024 09:48:20 +0200
Subject: [PATCH 43/81] feat: Add support for proposing transactions as a
delegate (#4017)
* feat: Add support for proposing transactions as a delegate
* fix: failing unit test
* fix: Sign transaction to remove untrusted status
* fix: Only get delegate if on a safe
* fix: Allow signing with hardware wallet
* fix: Add getDelegates RTK Query
* refactor: Extract logic into dispatch call, add wallet rejection error
* chore: Update gateway-sdk package to support delegates v2 endpoint, switch chain before signing
---
package.json | 2 +-
src/components/common/CheckWallet/index.tsx | 6 +-
.../common/WalletProvider/index.tsx | 1 +
.../settings/DelegatesList/index.tsx | 20 +--
.../tx/SignOrExecuteForm/DelegateForm.tsx | 119 ++++++++++++++++++
.../__tests__/ExecuteForm.test.tsx | 11 +-
.../__tests__/SignForm.test.tsx | 8 +-
src/components/tx/SignOrExecuteForm/hooks.ts | 17 ++-
src/components/tx/SignOrExecuteForm/index.tsx | 13 +-
src/hooks/useDelegates.ts | 22 ++++
.../wallets/__tests__/useOnboard.test.ts | 1 +
src/hooks/wallets/useOnboard.ts | 2 +
src/services/tx/tx-sender/dispatch.ts | 21 +++-
src/services/tx/tx-sender/sdk.ts | 2 +-
src/store/gateway.ts | 13 ++
yarn.lock | 8 +-
16 files changed, 228 insertions(+), 38 deletions(-)
create mode 100644 src/components/tx/SignOrExecuteForm/DelegateForm.tsx
create mode 100644 src/hooks/useDelegates.ts
diff --git a/package.json b/package.json
index 55d13e0af4..6fde28c067 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"@safe-global/protocol-kit": "^4.1.0",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-deployments": "^1.37.3",
- "@safe-global/safe-gateway-typescript-sdk": "3.22.1",
+ "@safe-global/safe-gateway-typescript-sdk": "3.22.2",
"@safe-global/safe-modules-deployments": "^1.2.0",
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
diff --git a/src/components/common/CheckWallet/index.tsx b/src/components/common/CheckWallet/index.tsx
index 9da8c9700e..59ab6e7c30 100644
--- a/src/components/common/CheckWallet/index.tsx
+++ b/src/components/common/CheckWallet/index.tsx
@@ -1,3 +1,4 @@
+import { useIsWalletDelegate } from '@/hooks/useDelegates'
import { type ReactElement } from 'react'
import { Tooltip } from '@mui/material'
import useIsOnlySpendingLimitBeneficiary from '@/hooks/useIsOnlySpendingLimitBeneficiary'
@@ -24,12 +25,15 @@ const CheckWallet = ({ children, allowSpendingLimit, allowNonOwner, noTooltip }:
const isSafeOwner = useIsSafeOwner()
const isSpendingLimit = useIsOnlySpendingLimitBeneficiary()
const connectWallet = useConnectWallet()
+ const isDelegate = useIsWalletDelegate()
const { safe } = useSafeInfo()
const isCounterfactualMultiSig = !allowNonOwner && !safe.deployed && safe.threshold > 1
const message =
- wallet && (isSafeOwner || allowNonOwner || (isSpendingLimit && allowSpendingLimit)) && !isCounterfactualMultiSig
+ wallet &&
+ (isSafeOwner || allowNonOwner || (isSpendingLimit && allowSpendingLimit) || isDelegate) &&
+ !isCounterfactualMultiSig
? ''
: !wallet
? Message.WalletNotConnected
diff --git a/src/components/common/WalletProvider/index.tsx b/src/components/common/WalletProvider/index.tsx
index f1c360c68d..6e14266d1a 100644
--- a/src/components/common/WalletProvider/index.tsx
+++ b/src/components/common/WalletProvider/index.tsx
@@ -13,6 +13,7 @@ const WalletProvider = ({ children }: { children: ReactNode }): ReactElement =>
const walletSubscription = onboard.state.select('wallets').subscribe((wallets) => {
const newWallet = getConnectedWallet(wallets)
+
setWallet(newWallet)
})
diff --git a/src/components/settings/DelegatesList/index.tsx b/src/components/settings/DelegatesList/index.tsx
index 1610e2db82..9aa65bb02c 100644
--- a/src/components/settings/DelegatesList/index.tsx
+++ b/src/components/settings/DelegatesList/index.tsx
@@ -1,28 +1,14 @@
-import { getDelegates } from '@safe-global/safe-gateway-typescript-sdk'
-import useAsync from '@/hooks/useAsync'
-import useSafeInfo from '@/hooks/useSafeInfo'
+import useDelegates from '@/hooks/useDelegates'
import { Box, Grid, Paper, SvgIcon, Tooltip, Typography } from '@mui/material'
import EthHashInfo from '@/components/common/EthHashInfo'
import InfoIcon from '@/public/images/notifications/info.svg'
import ExternalLink from '@/components/common/ExternalLink'
import { HelpCenterArticle } from '@/config/constants'
-const useDelegates = () => {
- const {
- safe: { chainId },
- safeAddress,
- } = useSafeInfo()
- const [delegates] = useAsync(() => {
- if (!chainId || !safeAddress) return
- return getDelegates(chainId, { safe: safeAddress })
- }, [chainId, safeAddress])
- return delegates
-}
-
const DelegatesList = () => {
const delegates = useDelegates()
- if (!delegates?.results.length) return null
+ if (!delegates.data?.results) return null
return (
@@ -55,7 +41,7 @@ const DelegatesList = () => {
- {delegates.results.map((item) => (
+ {delegates.data.results.map((item) => (
+ txSecurity: ReturnType
+ safeTx?: SafeTransaction
+}): ReactElement => {
+ // Form state
+ const [isSubmittable, setIsSubmittable] = useState(true)
+ const [isRejectedByUser, setIsRejectedByUser] = useState(false)
+
+ // Hooks
+ const wallet = useWallet()
+ const { signDelegateTx } = txActions
+ const { setTxFlow } = useContext(TxModalContext)
+ const { needsRiskConfirmation, isRiskConfirmed, setIsRiskIgnored } = txSecurity
+
+ // On modal submit
+ const handleSubmit = async (e: SyntheticEvent) => {
+ e.preventDefault()
+
+ if (needsRiskConfirmation && !isRiskConfirmed) {
+ setIsRiskIgnored(true)
+ return
+ }
+
+ if (!safeTx || !wallet) return
+
+ setIsSubmittable(false)
+ setIsRejectedByUser(false)
+
+ try {
+ await signDelegateTx(safeTx)
+ } catch (_err) {
+ const err = asError(_err)
+ if (isWalletRejection(err)) {
+ setIsRejectedByUser(true)
+ } else {
+ trackError(Errors._805, err)
+ }
+ setIsSubmittable(true)
+ return
+ }
+
+ setTxFlow(undefined)
+ }
+
+ const submitDisabled = !safeTx || !isSubmittable || disableSubmit || (needsRiskConfirmation && !isRiskConfirmed)
+
+ return (
+
+ )
+}
+
+const useTxSecurityContext = () => useContext(TxSecurityContext)
+
+export default madProps(DelegateForm, {
+ txActions: useTxActions,
+ txSecurity: useTxSecurityContext,
+})
diff --git a/src/components/tx/SignOrExecuteForm/__tests__/ExecuteForm.test.tsx b/src/components/tx/SignOrExecuteForm/__tests__/ExecuteForm.test.tsx
index 662a1a950b..60141794fd 100644
--- a/src/components/tx/SignOrExecuteForm/__tests__/ExecuteForm.test.tsx
+++ b/src/components/tx/SignOrExecuteForm/__tests__/ExecuteForm.test.tsx
@@ -33,7 +33,7 @@ describe('ExecuteForm', () => {
isOwner: true,
isExecutionLoop: false,
relays: [undefined, undefined, false] as AsyncResult,
- txActions: { signTx: jest.fn(), addToBatch: jest.fn(), executeTx: jest.fn() },
+ txActions: { signTx: jest.fn(), addToBatch: jest.fn(), executeTx: jest.fn(), signDelegateTx: jest.fn() },
txSecurity: defaultSecurityContextValues,
}
@@ -105,7 +105,10 @@ describe('ExecuteForm', () => {
.mockReturnValue({ executionValidationError: new Error('Some error'), isValidExecutionLoading: false })
const { getByText } = render(
- ,
+ ,
)
expect(
@@ -135,7 +138,7 @@ describe('ExecuteForm', () => {
{...defaultProps}
safeTx={safeTransaction}
onSubmit={jest.fn()}
- txActions={{ signTx: jest.fn(), addToBatch: jest.fn(), executeTx: mockExecuteTx }}
+ txActions={{ signTx: jest.fn(), addToBatch: jest.fn(), executeTx: mockExecuteTx, signDelegateTx: jest.fn() }}
/>,
)
@@ -155,7 +158,7 @@ describe('ExecuteForm', () => {
,
)
diff --git a/src/components/tx/SignOrExecuteForm/__tests__/SignForm.test.tsx b/src/components/tx/SignOrExecuteForm/__tests__/SignForm.test.tsx
index 25dd58fb2f..ea18ea7c9e 100644
--- a/src/components/tx/SignOrExecuteForm/__tests__/SignForm.test.tsx
+++ b/src/components/tx/SignOrExecuteForm/__tests__/SignForm.test.tsx
@@ -25,7 +25,7 @@ describe('SignForm', () => {
const defaultProps = {
onSubmit: jest.fn(),
isOwner: true,
- txActions: { signTx: jest.fn(), addToBatch: jest.fn(), executeTx: jest.fn() },
+ txActions: { signTx: jest.fn(), addToBatch: jest.fn(), executeTx: jest.fn(), signDelegateTx: jest.fn() },
txSecurity: defaultSecurityContextValues,
}
@@ -70,7 +70,7 @@ describe('SignForm', () => {
,
)
@@ -90,7 +90,7 @@ describe('SignForm', () => {
,
)
@@ -133,7 +133,7 @@ describe('SignForm', () => {
safeTx={safeTransaction}
isBatchable
isCreation
- txActions={{ signTx: jest.fn(), addToBatch: mockAddToBatch, executeTx: jest.fn() }}
+ txActions={{ signTx: jest.fn(), addToBatch: mockAddToBatch, executeTx: jest.fn(), signDelegateTx: jest.fn() }}
/>,
)
diff --git a/src/components/tx/SignOrExecuteForm/hooks.ts b/src/components/tx/SignOrExecuteForm/hooks.ts
index 9000ccedde..f84c16d33d 100644
--- a/src/components/tx/SignOrExecuteForm/hooks.ts
+++ b/src/components/tx/SignOrExecuteForm/hooks.ts
@@ -8,6 +8,7 @@ import useWallet from '@/hooks/wallets/useWallet'
import useOnboard from '@/hooks/wallets/useOnboard'
import { isSmartContractWallet } from '@/utils/wallets'
import {
+ dispatchDelegateTxSigning,
dispatchOnChainSigning,
dispatchTxExecution,
dispatchTxProposal,
@@ -31,6 +32,7 @@ type TxActions = {
origin?: string,
isRelayed?: boolean,
) => Promise
+ signDelegateTx: (safeTx?: SafeTransaction) => Promise
}
export const useTxActions = (): TxActions => {
@@ -98,6 +100,19 @@ export const useTxActions = (): TxActions => {
return tx.txId
}
+ const signDelegateTx: TxActions['signDelegateTx'] = async (safeTx) => {
+ assertTx(safeTx)
+ assertWallet(wallet)
+ assertOnboard(onboard)
+
+ await assertWalletChain(onboard, chainId)
+
+ const signedTx = await dispatchDelegateTxSigning(safeTx, wallet)
+
+ const tx = await proposeTx(wallet.address, signedTx)
+ return tx.txId
+ }
+
const executeTx: TxActions['executeTx'] = async (txOptions, safeTx, txId, origin, isRelayed) => {
assertTx(safeTx)
assertWallet(wallet)
@@ -137,7 +152,7 @@ export const useTxActions = (): TxActions => {
return txId
}
- return { addToBatch, signTx, executeTx }
+ return { addToBatch, signTx, executeTx, signDelegateTx }
}, [safe, wallet, addTxToBatch, onboard, chain])
}
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index ff3c299f38..03bcc49df6 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -1,4 +1,6 @@
+import DelegateForm from '@/components/tx/SignOrExecuteForm/DelegateForm'
import CounterfactualForm from '@/features/counterfactual/CounterfactualForm'
+import { useIsWalletDelegate } from '@/hooks/useDelegates'
import useSafeInfo from '@/hooks/useSafeInfo'
import { type ReactElement, type ReactNode, useState, useContext, useCallback } from 'react'
import madProps from '@/utils/mad-props'
@@ -103,6 +105,7 @@ export const SignOrExecuteForm = ({
: skipToken,
)
const showTxDetails = props.txId && txDetails && !isCustomTxInfo(txDetails.txInfo)
+ const isDelegate = useIsWalletDelegate()
const [trigger] = useLazyGetTransactionDetailsQuery()
const [readableApprovals] = useApprovalInfos({ safeTransaction: safeTx })
const isApproval = readableApprovals && readableApprovals.length > 0
@@ -189,7 +192,7 @@ export const SignOrExecuteForm = ({
)}
- {(canExecute || canExecuteThroughRole) && !props.onlyExecute && !isCounterfactualSafe && (
+ {(canExecute || canExecuteThroughRole) && !props.onlyExecute && !isCounterfactualSafe && !isDelegate && (
)}
@@ -199,10 +202,10 @@ export const SignOrExecuteForm = ({
- {isCounterfactualSafe && (
+ {isCounterfactualSafe && !isDelegate && (
)}
- {!isCounterfactualSafe && willExecute && (
+ {!isCounterfactualSafe && willExecute && !isDelegate && (
)}
{!isCounterfactualSafe && willExecuteThroughRole && (
@@ -214,7 +217,7 @@ export const SignOrExecuteForm = ({
role={(allowingRole || mostLikelyRole)!}
/>
)}
- {!isCounterfactualSafe && !willExecute && !willExecuteThroughRole && (
+ {!isCounterfactualSafe && !willExecute && !willExecuteThroughRole && !isDelegate && (
)}
+
+ {isDelegate && }
>
)
diff --git a/src/hooks/useDelegates.ts b/src/hooks/useDelegates.ts
new file mode 100644
index 0000000000..74c643ce33
--- /dev/null
+++ b/src/hooks/useDelegates.ts
@@ -0,0 +1,22 @@
+import useSafeInfo from '@/hooks/useSafeInfo'
+import useWallet from '@/hooks/wallets/useWallet'
+import { useGetDelegatesQuery } from '@/store/gateway'
+import { skipToken } from '@reduxjs/toolkit/query/react'
+
+const useDelegates = () => {
+ const {
+ safe: { chainId },
+ safeAddress,
+ } = useSafeInfo()
+
+ return useGetDelegatesQuery(chainId && safeAddress ? { chainId, safeAddress } : skipToken)
+}
+
+export const useIsWalletDelegate = () => {
+ const wallet = useWallet()
+ const delegates = useDelegates()
+
+ return delegates.data?.results.some((delegate) => delegate.delegate === wallet?.address)
+}
+
+export default useDelegates
diff --git a/src/hooks/wallets/__tests__/useOnboard.test.ts b/src/hooks/wallets/__tests__/useOnboard.test.ts
index 7fa1602c35..a885e21afa 100644
--- a/src/hooks/wallets/__tests__/useOnboard.test.ts
+++ b/src/hooks/wallets/__tests__/useOnboard.test.ts
@@ -51,6 +51,7 @@ describe('useOnboard', () => {
chainId: '4',
ens: 'test.eth',
balance: '0.00235 ETH',
+ isDelegate: false,
})
})
diff --git a/src/hooks/wallets/useOnboard.ts b/src/hooks/wallets/useOnboard.ts
index 69f9146476..583976d5ee 100644
--- a/src/hooks/wallets/useOnboard.ts
+++ b/src/hooks/wallets/useOnboard.ts
@@ -21,6 +21,7 @@ export type ConnectedWallet = {
provider: Eip1193Provider
icon?: string
balance?: string
+ isDelegate?: boolean
}
const { getStore, setStore, useStore } = new ExternalStore()
@@ -70,6 +71,7 @@ export const getConnectedWallet = (wallets: WalletState[]): ConnectedWallet | nu
provider: primaryWallet.provider,
icon: primaryWallet.icon,
balance,
+ isDelegate: false,
}
} catch (e) {
logError(Errors._106, e)
diff --git a/src/services/tx/tx-sender/dispatch.ts b/src/services/tx/tx-sender/dispatch.ts
index 6a698e76b9..d28f22f127 100644
--- a/src/services/tx/tx-sender/dispatch.ts
+++ b/src/services/tx/tx-sender/dispatch.ts
@@ -1,4 +1,5 @@
-import { isSmartContractWallet } from '@/utils/wallets'
+import type { ConnectedWallet } from '@/hooks/wallets/useOnboard'
+import { isHardwareWallet, isSmartContractWallet } from '@/utils/wallets'
import type { MultiSendCallOnlyContractImplementationType } from '@safe-global/protocol-kit'
import {
type ChainInfo,
@@ -7,6 +8,7 @@ import {
type TransactionDetails,
} from '@safe-global/safe-gateway-typescript-sdk'
import type {
+ SafeSignature,
SafeTransaction,
Transaction,
TransactionOptions,
@@ -108,6 +110,23 @@ export const dispatchTxSigning = async (
return signedTx
}
+// We have to manually sign because sdk.signTransaction doesn't support delegates
+export const dispatchDelegateTxSigning = async (safeTx: SafeTransaction, wallet: ConnectedWallet) => {
+ const sdk = await getSafeSDKWithSigner(wallet.provider)
+
+ let signature: SafeSignature
+ if (isHardwareWallet(wallet)) {
+ const txHash = await sdk.getTransactionHash(safeTx)
+ signature = await sdk.signHash(txHash)
+ } else {
+ signature = await sdk.signTypedData(safeTx)
+ }
+
+ safeTx.addSignature(signature)
+
+ return safeTx
+}
+
const ZK_SYNC_ON_CHAIN_SIGNATURE_GAS_LIMIT = 4_500_000
/**
diff --git a/src/services/tx/tx-sender/sdk.ts b/src/services/tx/tx-sender/sdk.ts
index 5b7e0aa518..ae00cebeb1 100644
--- a/src/services/tx/tx-sender/sdk.ts
+++ b/src/services/tx/tx-sender/sdk.ts
@@ -247,6 +247,6 @@ export const prepareApproveTxHash = async (hash: string, provider: Eip1193Provid
throw new Error('Transaction hashes can only be approved by Safe owners')
}
- // @ts-expect-error TS2590: Expression produces a union type that is too complex to represent.
+ // @ts-ignore
return safeContract.encode('approveHash', [hash])
}
diff --git a/src/store/gateway.ts b/src/store/gateway.ts
index 97eafa294e..3b027245b9 100644
--- a/src/store/gateway.ts
+++ b/src/store/gateway.ts
@@ -3,6 +3,8 @@ import { createApi } from '@reduxjs/toolkit/query/react'
import { getTransactionDetails, type TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import type { BaseQueryFn } from '@reduxjs/toolkit/dist/query/baseQueryTypes'
import type { FetchBaseQueryError } from '@reduxjs/toolkit/dist/query/react'
+import { getDelegates } from '@safe-global/safe-gateway-typescript-sdk'
+import type { DelegateResponse } from '@safe-global/safe-gateway-typescript-sdk/dist/types/delegates'
const noopBaseQuery: BaseQueryFn<
unknown, // QueryArg type
@@ -36,6 +38,16 @@ export const gatewayApi = createApi({
}
},
}),
+ getDelegates: builder.query({
+ async queryFn({ chainId, safeAddress }) {
+ try {
+ const delegates = await getDelegates(chainId, { safe: safeAddress })
+ return { data: delegates }
+ } catch (error) {
+ return { error: error as FetchBaseQueryError }
+ }
+ },
+ }),
}),
})
@@ -43,4 +55,5 @@ export const {
useGetTransactionDetailsQuery,
useGetMultipleTransactionDetailsQuery,
useLazyGetTransactionDetailsQuery,
+ useGetDelegatesQuery,
} = gatewayApi
diff --git a/yarn.lock b/yarn.lock
index 959d373c63..ec96dbd6ef 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4183,10 +4183,10 @@
dependencies:
semver "^7.6.2"
-"@safe-global/safe-gateway-typescript-sdk@3.22.1":
- version "3.22.1"
- resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.1.tgz#4d5dac21c6e044b68b13b53468633ec771f30e3b"
- integrity sha512-YApSpx+3h6uejrJVh8PSqXRRAwmsWz8PZERObMGJNC9NPoMhZG/Rvqb2UWmVLrjFh880rqutsB+GrTmJP351PA==
+"@safe-global/safe-gateway-typescript-sdk@3.22.2":
+ version "3.22.2"
+ resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.2.tgz#d4ff9972e58f9344fc95f8d41b2ec6517baa8e79"
+ integrity sha512-Y0yAxRaB98LFp2Dm+ACZqBSdAmI3FlpH/LjxOZ94g/ouuDJecSq0iR26XZ5QDuEL8Rf+L4jBJaoDC08CD0KkJw==
"@safe-global/safe-gateway-typescript-sdk@^3.5.3":
version "3.21.2"
From 45807e4573e7374c9277df93b893ac7a6e215a27 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Wed, 4 Sep 2024 10:02:07 +0200
Subject: [PATCH 44/81] Chore: update walletconnect packages (#4133)
---
package.json | 6 +--
yarn.lock | 119 +++++++++++++++++++++++----------------------------
2 files changed, 57 insertions(+), 68 deletions(-)
diff --git a/package.json b/package.json
index 6fde28c067..6b4cbde0af 100644
--- a/package.json
+++ b/package.json
@@ -62,8 +62,8 @@
"@safe-global/safe-modules-deployments": "^1.2.0",
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
- "@walletconnect/utils": "^2.13.1",
- "@walletconnect/web3wallet": "^1.12.1",
+ "@walletconnect/utils": "^2.15.2",
+ "@walletconnect/web3wallet": "^1.14.2",
"@web3-onboard/coinbase": "^2.2.6",
"@web3-onboard/core": "^2.21.4",
"@web3-onboard/injected-wallets": "^2.11.2",
@@ -128,7 +128,7 @@
"@types/react-gtm-module": "^2.0.3",
"@types/semver": "^7.3.10",
"@typescript-eslint/eslint-plugin": "^7.6.0",
- "@walletconnect/types": "^2.13.1",
+ "@walletconnect/types": "^2.15.2",
"cross-env": "^7.0.3",
"cypress": "^12.15.0",
"cypress-file-upload": "^5.0.8",
diff --git a/yarn.lock b/yarn.lock
index ec96dbd6ef..65acb87bf9 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6449,10 +6449,10 @@
lodash.isequal "4.5.0"
uint8arrays "^3.1.0"
-"@walletconnect/core@2.13.1":
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.13.1.tgz#a59646e39a5beaa3f3551d129af43cd404cf4faf"
- integrity sha512-h0MSYKJu9i1VEs5koCTT7c5YeQ1Kj0ncTFiMqANbDnB1r3mBulXn+FKtZ2fCmf1j7KDpgluuUzpSs+sQfPcv4Q==
+"@walletconnect/core@2.15.2":
+ version "2.15.2"
+ resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.15.2.tgz#12d9da8c4e32a6c3713f421ca65cd0605f43a080"
+ integrity sha512-u4BGuazSNAQ48QBY7EphanBuBN6EJWyD5MXi83n1wXwfPQWAu0XNvmOjjF+xmMI5TsYH9N6Y78O6HP/VX9EOvg==
dependencies:
"@walletconnect/heartbeat" "1.2.2"
"@walletconnect/jsonrpc-provider" "1.0.14"
@@ -6461,14 +6461,13 @@
"@walletconnect/jsonrpc-ws-connection" "1.0.14"
"@walletconnect/keyvaluestorage" "1.1.1"
"@walletconnect/logger" "2.1.2"
- "@walletconnect/relay-api" "1.0.10"
+ "@walletconnect/relay-api" "1.0.11"
"@walletconnect/relay-auth" "1.0.4"
"@walletconnect/safe-json" "1.0.2"
"@walletconnect/time" "1.0.2"
- "@walletconnect/types" "2.13.1"
- "@walletconnect/utils" "2.13.1"
+ "@walletconnect/types" "2.15.2"
+ "@walletconnect/utils" "2.15.2"
events "3.3.0"
- isomorphic-unfetch "3.1.0"
lodash.isequal "4.5.0"
uint8arrays "3.1.0"
@@ -6657,10 +6656,10 @@
"@walletconnect/modal-core" "2.6.2"
"@walletconnect/modal-ui" "2.6.2"
-"@walletconnect/relay-api@1.0.10":
- version "1.0.10"
- resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.10.tgz#5aef3cd07c21582b968136179aa75849dcc65499"
- integrity sha512-tqrdd4zU9VBNqUaXXQASaexklv6A54yEyQQEXYOCr+Jz8Ket0dmPBDyg19LVSNUN2cipAghQc45/KVmfFJ0cYw==
+"@walletconnect/relay-api@1.0.11":
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/@walletconnect/relay-api/-/relay-api-1.0.11.tgz#80ab7ef2e83c6c173be1a59756f95e515fb63224"
+ integrity sha512-tLPErkze/HmC9aCmdZOhtVmYZq1wKfWTJtygQHoWtgg722Jd4homo54Cs4ak2RUFUZIGO2RsOpIcWipaua5D5Q==
dependencies:
"@walletconnect/jsonrpc-types" "^1.0.2"
@@ -6706,19 +6705,19 @@
"@walletconnect/utils" "2.11.2"
events "^3.3.0"
-"@walletconnect/sign-client@2.13.1":
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.13.1.tgz#7bdc9226218fd33caf3aef69dff0b4140abc7fa8"
- integrity sha512-e+dcqcLsedB4ZjnePFM5Cy8oxu0dyz5iZfhfKH/MOrQV/hyhZ+hJwh4MmkO2QyEu2PERKs9o2Uc6x8RZdi0UAQ==
+"@walletconnect/sign-client@2.15.2":
+ version "2.15.2"
+ resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.15.2.tgz#4568f71f6daebc6405d86278c78b64ef646c266b"
+ integrity sha512-Yp4/z3IdTMngbjr7Zy7Qi1X6EZDH4nxY91X6K2KpA3MjLW0yPTGalEJgJ4p9WH7fmHRlwvfR4hjwM5eQcLo5Zg==
dependencies:
- "@walletconnect/core" "2.13.1"
+ "@walletconnect/core" "2.15.2"
"@walletconnect/events" "1.0.1"
"@walletconnect/heartbeat" "1.2.2"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "2.1.2"
"@walletconnect/time" "1.0.2"
- "@walletconnect/types" "2.13.1"
- "@walletconnect/utils" "2.13.1"
+ "@walletconnect/types" "2.15.2"
+ "@walletconnect/utils" "2.15.2"
events "3.3.0"
"@walletconnect/time@1.0.2", "@walletconnect/time@^1.0.2":
@@ -6752,10 +6751,10 @@
"@walletconnect/logger" "^2.0.1"
events "^3.3.0"
-"@walletconnect/types@2.13.1", "@walletconnect/types@^2.13.1":
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.13.1.tgz#393e3bd4d60a755f3a70cbe769b58cf153450310"
- integrity sha512-CIrdt66d38xdunGCy5peOOP17EQkCEGKweXc3+Gn/RWeSiRU35I7wjC/Bp4iWcgAQ6iBTZv4jGGST5XyrOp+Pg==
+"@walletconnect/types@2.15.2", "@walletconnect/types@^2.15.2":
+ version "2.15.2"
+ resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.15.2.tgz#b9e1746d8c7b9c7b08ed8f6696c86e44b645fe52"
+ integrity sha512-TGnQZYWZJJ3I8dqgpMPwhO1IRXDuY8/tWPI0nNWJDyTK7b3E9prDGugnPmDDjpTYVoETnUTgW/jQaHNTq4yV7Q==
dependencies:
"@walletconnect/events" "1.0.1"
"@walletconnect/heartbeat" "1.2.2"
@@ -6819,39 +6818,41 @@
query-string "7.1.3"
uint8arrays "^3.1.0"
-"@walletconnect/utils@2.13.1", "@walletconnect/utils@^2.13.1":
- version "2.13.1"
- resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.13.1.tgz#f44e81028754c6e056dba588ad9b9fa5ad047645"
- integrity sha512-EcooXXlqy5hk9hy/nK2wBF/qxe7HjH0K8ZHzjKkXRkwAE5pCvy0IGXIXWmUR9sw8LFJEqZyd8rZdWLKNUe8hqA==
+"@walletconnect/utils@2.15.2", "@walletconnect/utils@^2.15.2":
+ version "2.15.2"
+ resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.15.2.tgz#6fba3e28d00afe15b499409d609e3faafcef1887"
+ integrity sha512-H+fNH9cHDezdaEiEsO7/3URSIzqhumuacwB/+0PX0sSCoktmU9AfTqA8fJGG43zOPixleBqOymzO6owB1Y7jtQ==
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.10"
+ "@walletconnect/relay-api" "1.0.11"
+ "@walletconnect/relay-auth" "1.0.4"
"@walletconnect/safe-json" "1.0.2"
"@walletconnect/time" "1.0.2"
- "@walletconnect/types" "2.13.1"
+ "@walletconnect/types" "2.15.2"
"@walletconnect/window-getters" "1.0.1"
"@walletconnect/window-metadata" "1.0.1"
detect-browser "5.3.0"
+ elliptic "^6.5.7"
query-string "7.1.3"
uint8arrays "3.1.0"
-"@walletconnect/web3wallet@^1.12.1":
- version "1.12.1"
- resolved "https://registry.yarnpkg.com/@walletconnect/web3wallet/-/web3wallet-1.12.1.tgz#efe7863c6518b2262bca1ea01650222986963cc4"
- integrity sha512-34h7UkWjZvZdtCc/t6tZCSBPjDzJbfG1+OPkJ6FiD1KJP+a0wSwuI7l4LliGgvAdsXfrM+sn3ZEWVWy62zeRDA==
+"@walletconnect/web3wallet@^1.14.2":
+ version "1.14.2"
+ resolved "https://registry.yarnpkg.com/@walletconnect/web3wallet/-/web3wallet-1.14.2.tgz#cace0f3b662c08183f60e79b5f491e116e1ec9fd"
+ integrity sha512-SN1uBW0oRMZHFe8ZKS9EDcqsn0Z1Iac8unKA+60SLQRlZKjyOQ++BTpEsIkJWfPE/WNDZKV8axK+8VI8xxybCA==
dependencies:
"@walletconnect/auth-client" "2.1.2"
- "@walletconnect/core" "2.13.1"
+ "@walletconnect/core" "2.15.2"
"@walletconnect/jsonrpc-provider" "1.0.14"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "2.1.2"
- "@walletconnect/sign-client" "2.13.1"
- "@walletconnect/types" "2.13.1"
- "@walletconnect/utils" "2.13.1"
+ "@walletconnect/sign-client" "2.15.2"
+ "@walletconnect/types" "2.15.2"
+ "@walletconnect/utils" "2.15.2"
"@walletconnect/window-getters@1.0.1", "@walletconnect/window-getters@^1.0.1":
version "1.0.1"
@@ -9616,6 +9617,19 @@ elliptic@^6.4.0, elliptic@^6.4.1, elliptic@^6.5.2, elliptic@^6.5.3, elliptic@^6.
minimalistic-assert "^1.0.1"
minimalistic-crypto-utils "^1.0.1"
+elliptic@^6.5.7:
+ version "6.5.7"
+ resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.7.tgz#8ec4da2cb2939926a1b9a73619d768207e647c8b"
+ integrity sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==
+ dependencies:
+ bn.js "^4.11.9"
+ brorand "^1.1.0"
+ hash.js "^1.0.0"
+ hmac-drbg "^1.0.1"
+ inherits "^2.0.4"
+ minimalistic-assert "^1.0.1"
+ minimalistic-crypto-utils "^1.0.1"
+
emittery@^0.13.1:
version "0.13.1"
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad"
@@ -16672,16 +16686,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16769,14 +16774,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", 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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18461,7 +18459,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18479,15 +18477,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From 66cbb30141d9505db9c32d18db52ab8bf00bc62e Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Wed, 4 Sep 2024 10:02:50 +0200
Subject: [PATCH 45/81] Fix: (css) center-align delegate warning (#4134)
---
src/components/transactions/Warning/index.tsx | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/components/transactions/Warning/index.tsx b/src/components/transactions/Warning/index.tsx
index d5123dac47..049ab9842a 100644
--- a/src/components/transactions/Warning/index.tsx
+++ b/src/components/transactions/Warning/index.tsx
@@ -22,7 +22,7 @@ const Warning = ({
`3px solid ${palette[severity].main} !important` }}
+ sx={{ borderLeft: ({ palette }) => `3px solid ${palette[severity].main} !important`, alignItems: 'center' }}
severity={severity}
icon={ }
>
From a473eb2b7462e828b1ccd470364efec015b08bf2 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 9 Sep 2024 09:06:41 +0200
Subject: [PATCH 46/81] Chore(deps): Bump @walletconnect/web3wallet from 1.14.2
to 1.15.0 (#4138)
Bumps [@walletconnect/web3wallet](https://github.com/walletconnect/walletconnect-monorepo) from 1.14.2 to 1.15.0.
- [Release notes](https://github.com/walletconnect/walletconnect-monorepo/releases)
- [Commits](https://github.com/walletconnect/walletconnect-monorepo/commits)
---
updated-dependencies:
- dependency-name: "@walletconnect/web3wallet"
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 160 ++++++++++++++++++++-------------------------------
2 files changed, 62 insertions(+), 100 deletions(-)
diff --git a/package.json b/package.json
index 6b4cbde0af..a6dca47ab7 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
"@walletconnect/utils": "^2.15.2",
- "@walletconnect/web3wallet": "^1.14.2",
+ "@walletconnect/web3wallet": "^1.15.0",
"@web3-onboard/coinbase": "^2.2.6",
"@web3-onboard/core": "^2.21.4",
"@web3-onboard/injected-wallets": "^2.11.2",
diff --git a/yarn.lock b/yarn.lock
index 65acb87bf9..cdfa93eeaf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6449,10 +6449,10 @@
lodash.isequal "4.5.0"
uint8arrays "^3.1.0"
-"@walletconnect/core@2.15.2":
- version "2.15.2"
- resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.15.2.tgz#12d9da8c4e32a6c3713f421ca65cd0605f43a080"
- integrity sha512-u4BGuazSNAQ48QBY7EphanBuBN6EJWyD5MXi83n1wXwfPQWAu0XNvmOjjF+xmMI5TsYH9N6Y78O6HP/VX9EOvg==
+"@walletconnect/core@2.16.0", "@walletconnect/core@^2.10.1":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.16.0.tgz#751eb0b9bcd24a0035c87a1be63c830b86dad3de"
+ integrity sha512-B/PPcg0MRb9pqB6nupVqEFGI5cFK5HNXYoi+y6Qaq53JIjHa6KANskNkj567iegETaPUZIniHENry7M8mHN3Bw==
dependencies:
"@walletconnect/heartbeat" "1.2.2"
"@walletconnect/jsonrpc-provider" "1.0.14"
@@ -6465,35 +6465,12 @@
"@walletconnect/relay-auth" "1.0.4"
"@walletconnect/safe-json" "1.0.2"
"@walletconnect/time" "1.0.2"
- "@walletconnect/types" "2.15.2"
- "@walletconnect/utils" "2.15.2"
+ "@walletconnect/types" "2.16.0"
+ "@walletconnect/utils" "2.16.0"
events "3.3.0"
lodash.isequal "4.5.0"
uint8arrays "3.1.0"
-"@walletconnect/core@^2.10.1":
- version "2.11.3"
- resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.11.3.tgz#c81855722cb9afd411f91f5345c7874f48bade0b"
- integrity sha512-/9m4EqiggFUwkQDv5PDWbcTI+yCVnBd/iYW5iIHEkivg2/mnBr2bQz2r/vtPjp19r/ZK62Dx0+UN3U+BWP8ulQ==
- dependencies:
- "@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.11.3"
- "@walletconnect/utils" "2.11.3"
- events "^3.3.0"
- isomorphic-unfetch "3.1.0"
- lodash.isequal "4.5.0"
- uint8arrays "^3.1.0"
-
"@walletconnect/environment@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@walletconnect/environment/-/environment-1.0.1.tgz#1d7f82f0009ab821a2ba5ad5e5a7b8ae3b214cd7"
@@ -6553,7 +6530,7 @@
cross-fetch "^3.1.4"
tslib "1.14.1"
-"@walletconnect/jsonrpc-provider@1.0.13", "@walletconnect/jsonrpc-provider@^1.0.13":
+"@walletconnect/jsonrpc-provider@1.0.13":
version "1.0.13"
resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.13.tgz#9a74da648d015e1fffc745f0c7d629457f53648b"
integrity sha512-K73EpThqHnSR26gOyNEL+acEex3P7VWZe6KE12ZwKzAt2H4e5gldZHbjsu2QR9cLeJ8AXuO7kEMOIcRv1QEc7g==
@@ -6562,7 +6539,7 @@
"@walletconnect/safe-json" "^1.0.2"
tslib "1.14.1"
-"@walletconnect/jsonrpc-provider@1.0.14":
+"@walletconnect/jsonrpc-provider@1.0.14", "@walletconnect/jsonrpc-provider@^1.0.13":
version "1.0.14"
resolved "https://registry.yarnpkg.com/@walletconnect/jsonrpc-provider/-/jsonrpc-provider-1.0.14.tgz#696f3e3b6d728b361f2e8b853cfc6afbdf2e4e3e"
integrity sha512-rtsNY1XqHvWj0EtITNeuf8PHMvlCLiS3EjQL+WOkxEOA4KPxsohFnBDeyPYiNm4ZvkQdLnece36opYidmtbmow==
@@ -6615,7 +6592,7 @@
idb-keyval "^6.2.1"
unstorage "^1.9.0"
-"@walletconnect/logger@2.1.2":
+"@walletconnect/logger@2.1.2", "@walletconnect/logger@^2.0.1":
version "2.1.2"
resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.1.2.tgz#813c9af61b96323a99f16c10089bfeb525e2a272"
integrity sha512-aAb28I3S6pYXZHQm5ESB+V6rDqIYfsnHaQyzFbwUUBFY4H0OXx/YtTl8lvhUNhMMfb9UxbwEBS253TlXUYJWSw==
@@ -6623,14 +6600,6 @@
"@walletconnect/safe-json" "^1.0.2"
pino "7.11.0"
-"@walletconnect/logger@^2.0.1":
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/@walletconnect/logger/-/logger-2.0.1.tgz#7f489b96e9a1ff6bf3e58f0fbd6d69718bf844a8"
- integrity sha512-SsTKdsgWm+oDTBeNE/zHxxr5eJfZmE9/5yp/Ku+zJtcTAjELb3DXueWkDXmE9h8uHIbJzIb5wj5lPdzyrjT6hQ==
- dependencies:
- pino "7.11.0"
- tslib "1.14.1"
-
"@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"
@@ -6705,19 +6674,19 @@
"@walletconnect/utils" "2.11.2"
events "^3.3.0"
-"@walletconnect/sign-client@2.15.2":
- version "2.15.2"
- resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.15.2.tgz#4568f71f6daebc6405d86278c78b64ef646c266b"
- integrity sha512-Yp4/z3IdTMngbjr7Zy7Qi1X6EZDH4nxY91X6K2KpA3MjLW0yPTGalEJgJ4p9WH7fmHRlwvfR4hjwM5eQcLo5Zg==
+"@walletconnect/sign-client@2.16.0":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.16.0.tgz#80abe30b86431e6c2e3287a98df973203fec1559"
+ integrity sha512-R9C9D8jaARbosXvA9IGIAowashGqp9avmjx6gikH4lKq2qhDjD5CWZq+GrN6gcht6WQiQ1mNmrmhN1pBPvivwQ==
dependencies:
- "@walletconnect/core" "2.15.2"
+ "@walletconnect/core" "2.16.0"
"@walletconnect/events" "1.0.1"
"@walletconnect/heartbeat" "1.2.2"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "2.1.2"
"@walletconnect/time" "1.0.2"
- "@walletconnect/types" "2.15.2"
- "@walletconnect/utils" "2.15.2"
+ "@walletconnect/types" "2.16.0"
+ "@walletconnect/utils" "2.16.0"
events "3.3.0"
"@walletconnect/time@1.0.2", "@walletconnect/time@^1.0.2":
@@ -6739,22 +6708,10 @@
"@walletconnect/logger" "^2.0.1"
events "^3.3.0"
-"@walletconnect/types@2.11.3":
- version "2.11.3"
- resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.11.3.tgz#8ce43cb77e8fd9d5269847cdd73bcfa7cce7dd1a"
- integrity sha512-JY4wA9MVosDW9dcJMTpnwliste0aJGJ1X6Q4ulLsQsgWRSEBRkLila0oUT01TDBW9Yq8uUp7uFOUTaKx6KWVAg==
- 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@2.15.2", "@walletconnect/types@^2.15.2":
- version "2.15.2"
- resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.15.2.tgz#b9e1746d8c7b9c7b08ed8f6696c86e44b645fe52"
- integrity sha512-TGnQZYWZJJ3I8dqgpMPwhO1IRXDuY8/tWPI0nNWJDyTK7b3E9prDGugnPmDDjpTYVoETnUTgW/jQaHNTq4yV7Q==
+"@walletconnect/types@2.16.0", "@walletconnect/types@^2.15.2":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.16.0.tgz#1719bbde7bd6316e8167ab47e6cbb441c4f168dc"
+ integrity sha512-n+vpli0eonAzG9wtOgmjYbJEMGz2gvOttU2VnzNkeVmvDz7otVuPgtk+7BNyRofZ6rBW6rriW5cCKtmbzvUSzA==
dependencies:
"@walletconnect/events" "1.0.1"
"@walletconnect/heartbeat" "1.2.2"
@@ -6798,30 +6755,10 @@
query-string "7.1.3"
uint8arrays "^3.1.0"
-"@walletconnect/utils@2.11.3", "@walletconnect/utils@^2.10.1":
- version "2.11.3"
- resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.11.3.tgz#3731809b54902655cf202e0bf0e8f268780e8b54"
- integrity sha512-jsdNkrl/IcTkzWFn0S2d0urzBXg6RxVJtUYRsUx3qI3wzOGiABP9ui3yiZ3SgZOv9aRe62PaNp1qpbYZ+zPb8Q==
- 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.11.3"
- "@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/utils@2.15.2", "@walletconnect/utils@^2.15.2":
- version "2.15.2"
- resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.15.2.tgz#6fba3e28d00afe15b499409d609e3faafcef1887"
- integrity sha512-H+fNH9cHDezdaEiEsO7/3URSIzqhumuacwB/+0PX0sSCoktmU9AfTqA8fJGG43zOPixleBqOymzO6owB1Y7jtQ==
+"@walletconnect/utils@2.16.0", "@walletconnect/utils@^2.10.1", "@walletconnect/utils@^2.15.2":
+ version "2.16.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.16.0.tgz#0696655035dce9efcc209e5c789b7e22b085a70d"
+ integrity sha512-ASh9yyqzP4GLIU400rKEvBefcM5GFJbi2Iw7p0SFDyFC5WZYYyllU3WopU+YV/7bbukCMkthEIdioWYlpmjERQ==
dependencies:
"@stablelib/chacha20poly1305" "1.0.1"
"@stablelib/hkdf" "1.0.1"
@@ -6832,7 +6769,7 @@
"@walletconnect/relay-auth" "1.0.4"
"@walletconnect/safe-json" "1.0.2"
"@walletconnect/time" "1.0.2"
- "@walletconnect/types" "2.15.2"
+ "@walletconnect/types" "2.16.0"
"@walletconnect/window-getters" "1.0.1"
"@walletconnect/window-metadata" "1.0.1"
detect-browser "5.3.0"
@@ -6840,19 +6777,19 @@
query-string "7.1.3"
uint8arrays "3.1.0"
-"@walletconnect/web3wallet@^1.14.2":
- version "1.14.2"
- resolved "https://registry.yarnpkg.com/@walletconnect/web3wallet/-/web3wallet-1.14.2.tgz#cace0f3b662c08183f60e79b5f491e116e1ec9fd"
- integrity sha512-SN1uBW0oRMZHFe8ZKS9EDcqsn0Z1Iac8unKA+60SLQRlZKjyOQ++BTpEsIkJWfPE/WNDZKV8axK+8VI8xxybCA==
+"@walletconnect/web3wallet@^1.15.0":
+ version "1.15.0"
+ resolved "https://registry.yarnpkg.com/@walletconnect/web3wallet/-/web3wallet-1.15.0.tgz#745fab0d0fc22e0ce1c5f9880c865dde3aaa3e8e"
+ integrity sha512-tJbH/I8MJrKSEiLGlj0wmB4J1bB0dBoY1hRFMX3CCCkCB+ZFvJeoeC5LjTJRtSOqCk10ABp9uvII/18tYyxXnA==
dependencies:
"@walletconnect/auth-client" "2.1.2"
- "@walletconnect/core" "2.15.2"
+ "@walletconnect/core" "2.16.0"
"@walletconnect/jsonrpc-provider" "1.0.14"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "2.1.2"
- "@walletconnect/sign-client" "2.15.2"
- "@walletconnect/types" "2.15.2"
- "@walletconnect/utils" "2.15.2"
+ "@walletconnect/sign-client" "2.16.0"
+ "@walletconnect/types" "2.16.0"
+ "@walletconnect/utils" "2.16.0"
"@walletconnect/window-getters@1.0.1", "@walletconnect/window-getters@^1.0.1":
version "1.0.1"
@@ -16686,7 +16623,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16774,7 +16720,14 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18459,7 +18412,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18477,6 +18430,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From 62ca4519cbed8e99da1b51b0dd96b7c3bbea7d96 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 9 Sep 2024 09:07:36 +0200
Subject: [PATCH 47/81] Chore(deps): Bump classnames from 2.3.2 to 2.5.1
(#4137)
Bumps [classnames](https://github.com/JedWatson/classnames) from 2.3.2 to 2.5.1.
- [Changelog](https://github.com/JedWatson/classnames/blob/main/HISTORY.md)
- [Commits](https://github.com/JedWatson/classnames/compare/v2.3.2...v2.5.1)
---
updated-dependencies:
- dependency-name: classnames
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index a6dca47ab7..c7d20ee6bd 100644
--- a/package.json
+++ b/package.json
@@ -72,7 +72,7 @@
"@web3-onboard/trezor": "^2.4.2",
"@web3-onboard/walletconnect": "^2.5.4",
"blo": "^1.1.1",
- "classnames": "^2.3.1",
+ "classnames": "^2.5.1",
"date-fns": "^2.30.0",
"ethers": "^6.11.1",
"exponential-backoff": "^3.1.0",
diff --git a/yarn.lock b/yarn.lock
index cdfa93eeaf..7d8b6899ad 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -8379,10 +8379,10 @@ cjs-module-lexer@^1.0.0, cjs-module-lexer@^1.2.3:
resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107"
integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==
-classnames@^2.3.1:
- version "2.3.2"
- resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.2.tgz#351d813bf0137fcc6a76a16b88208d2560a0d924"
- integrity sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw==
+classnames@^2.5.1:
+ version "2.5.1"
+ resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.5.1.tgz#ba774c614be0f016da105c858e7159eae8e7687b"
+ integrity sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==
clean-css@^5.2.2:
version "5.3.3"
From 426b63a95d97294ada3d15b63c82a088b037d017 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=B3vis=20Neto?=
Date: Mon, 9 Sep 2024 12:38:24 +0200
Subject: [PATCH 48/81] fix: put execute button to be full width on mobile
display (#4143)
---
.github/workflows/cla.yml | 2 +-
src/components/tx/SignOrExecuteForm/ExecuteForm.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/cla.yml b/.github/workflows/cla.yml
index e7d985b475..14d1fef05a 100644
--- a/.github/workflows/cla.yml
+++ b/.github/workflows/cla.yml
@@ -24,7 +24,7 @@ jobs:
# branch should not be protected
branch: 'main'
# user names of users allowed to contribute without CLA
- allowlist: lukasschor,rmeissner,germartinez,Uxio0,dasanra,francovenica,tschubotz,luarx,DaniSomoza,iamacook,yagopv,usame-algan,schmanu,DiogoSoaress,JagoFigueroa,fmrsabino,mike10ca,jmealy,compojoom,TanyaEfremova,bot*
+ allowlist: clovisdasilvaneto,lukasschor,rmeissner,germartinez,Uxio0,dasanra,francovenica,tschubotz,luarx,DaniSomoza,iamacook,yagopv,usame-algan,schmanu,DiogoSoaress,JagoFigueroa,fmrsabino,mike10ca,jmealy,compojoom,TanyaEfremova,bot*
# the followings are the optional inputs - If the optional inputs are not given, then default values will be taken
# enter the remote organization name where the signatures should be stored (Default is storing the signatures in the same repository)
diff --git a/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx b/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx
index 9d4d4f862a..2022021a38 100644
--- a/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx
+++ b/src/components/tx/SignOrExecuteForm/ExecuteForm.tsx
@@ -195,7 +195,7 @@ export const ExecuteForm = ({
variant="contained"
type="submit"
disabled={!isOk || submitDisabled}
- sx={{ minWidth: '112px' }}
+ sx={{ minWidth: '112px', width: ['100%', '100%', '100%', 'auto'] }}
>
{!isSubmittable ? : 'Execute'}
From 2112060125abea347e0113ef74c233fc676d123c Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Mon, 9 Sep 2024 13:56:56 +0200
Subject: [PATCH 49/81] Fix: (Swaps) sell token reactivity (#4145)
---
src/features/swap/index.tsx | 8 ++++++++
src/pages/swap.tsx | 13 +++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/src/features/swap/index.tsx b/src/features/swap/index.tsx
index 1960b2761d..10f5a34fa8 100644
--- a/src/features/swap/index.tsx
+++ b/src/features/swap/index.tsx
@@ -274,6 +274,14 @@ const SwapWidget = ({ sell }: Params) => {
}))
}, [palette, darkMode, chainId])
+ useEffect(() => {
+ if (!sell) return
+ setParams((params) => ({
+ ...params,
+ sell,
+ }))
+ }, [sell])
+
const chain = useCurrentChain()
const iframeRef: MutableRefObject = useRef(null)
diff --git a/src/pages/swap.tsx b/src/pages/swap.tsx
index 297affc64e..35c3cf2aba 100644
--- a/src/pages/swap.tsx
+++ b/src/pages/swap.tsx
@@ -6,6 +6,15 @@ import { useContext } from 'react'
import { AppRoutes } from '@/config/routes'
import dynamic from 'next/dynamic'
+// Cow Swap expects native token addresses to be in the format '0xeeee...eeee'
+const adjustEthAddress = (address: string) => {
+ if (address && Number(address) === 0) {
+ const ETH_ADDRESS = '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'
+ return ETH_ADDRESS
+ }
+ return address
+}
+
const SwapWidgetNoSSR = dynamic(() => import('@/features/swap'), { ssr: false })
const Swap: NextPage = () => {
const router = useRouter()
@@ -19,8 +28,8 @@ const Swap: NextPage = () => {
let sell = undefined
if (token && amount) {
sell = {
- asset: String(token),
- amount: String(amount),
+ asset: adjustEthAddress(String(token ?? '')),
+ amount: adjustEthAddress(String(amount ?? '')),
}
}
From b04d5eddb0b532fa8f07e7b672a3fe7dd545a39d Mon Sep 17 00:00:00 2001
From: Michael <30682308+mike10ca@users.noreply.github.com>
Date: Mon, 9 Sep 2024 14:21:57 +0200
Subject: [PATCH 50/81] Tests: Fix failing regression tests (#4144)
* Fix failing regression tests
---
cypress/e2e/pages/create_tx.pages.js | 1 -
cypress/e2e/pages/create_wallet.pages.js | 5 +++++
cypress/e2e/regression/create_safe_cf.cy.js | 3 ++-
cypress/e2e/regression/create_safe_simple.cy.js | 3 +--
4 files changed, 8 insertions(+), 4 deletions(-)
diff --git a/cypress/e2e/pages/create_tx.pages.js b/cypress/e2e/pages/create_tx.pages.js
index 24fc822604..a5ef52a0b5 100644
--- a/cypress/e2e/pages/create_tx.pages.js
+++ b/cypress/e2e/pages/create_tx.pages.js
@@ -484,7 +484,6 @@ export function openExecutionParamsModal() {
export function verifyAndSubmitExecutionParams() {
cy.contains(executionParamsStr).parents('form').as('Paramsform')
-
const arrayNames = ['Wallet nonce', 'Max priority fee (Gwei)', 'Max fee (Gwei)', 'Gas limit']
arrayNames.forEach((element) => {
cy.get('@Paramsform').find('label').contains(`${element}`).next().find('input').should('not.be.disabled')
diff --git a/cypress/e2e/pages/create_wallet.pages.js b/cypress/e2e/pages/create_wallet.pages.js
index 508733ce49..ce62d6a7a4 100644
--- a/cypress/e2e/pages/create_wallet.pages.js
+++ b/cypress/e2e/pages/create_wallet.pages.js
@@ -49,8 +49,13 @@ const initialSteps = '0 of 2 steps completed'
export const addSignerStr = 'Add signer'
export const accountRecoveryStr = 'Account recovery'
export const sendTokensStr = 'Send tokens'
+const noWalletConnectedMsg = 'No wallet connected'
const connectWalletBtn = '[data-testid="connect-wallet-btn"]'
+
+export function waitForConnectionMsgDisappear() {
+ cy.contains(noWalletConnectedMsg).should('not.exist')
+}
export function checkNotificationsSwitchIs(status) {
cy.get(notificationsSwitch).find('input').should(`be.${status}`)
}
diff --git a/cypress/e2e/regression/create_safe_cf.cy.js b/cypress/e2e/regression/create_safe_cf.cy.js
index 874c635496..6bdf9a2bed 100644
--- a/cypress/e2e/regression/create_safe_cf.cy.js
+++ b/cypress/e2e/regression/create_safe_cf.cy.js
@@ -154,8 +154,9 @@ describe('CF Safe regression tests', () => {
it('Verify clicking on "Activate now" button opens safe activation flow', () => {
main.addToLocalStorage(constants.localStorageKeys.SAFE_v2__undeployedSafes, ls.undeployedSafe.safe1)
- cy.reload()
cy.visit(constants.BALANCE_URL + staticSafes.SEP_STATIC_SAFE_0)
+ wallet.connectSigner(signer)
+ owner.waitForConnectionStatus()
createwallet.clickOnActivateAccountBtn()
main.verifyElementsIsVisible([createwallet.activateAccountBtn])
})
diff --git a/cypress/e2e/regression/create_safe_simple.cy.js b/cypress/e2e/regression/create_safe_simple.cy.js
index 6fd0b63522..2156f218e7 100644
--- a/cypress/e2e/regression/create_safe_simple.cy.js
+++ b/cypress/e2e/regression/create_safe_simple.cy.js
@@ -134,8 +134,7 @@ describe('Safe creation tests', () => {
main.addToLocalStorage(constants.localStorageKeys.SAFE_v2__addressBook, ls.addressBookData.sameOwnerName),
)
.then(() => {
- createwallet.clickOnContinueWithWalletBtn()
- createwallet.clickOnCreateNewSafeBtn()
+ createwallet.waitForConnectionMsgDisappear()
createwallet.clickOnNextBtn()
createwallet.clickOnAddNewOwnerBtn()
createwallet.clickOnSignerAddressInput(1)
From 0c268e6e0adb3a239d4c8551f16103c2e9d0b9d0 Mon Sep 17 00:00:00 2001
From: Usame Algan <5880855+usame-algan@users.noreply.github.com>
Date: Mon, 9 Sep 2024 16:47:03 +0200
Subject: [PATCH 51/81] fix: Watch nested safe transactions (#4057)
* fix: Watch nested safe transactions
* fix: Add tests for useTxMonitor
* fix: Add happy path test cases for useTxPendingStatuses hook
---
.../__tests__/useTxPendingStatus.test.ts | 337 ++++++++++++++++++
src/hooks/useTxPendingStatuses.ts | 5 +-
src/services/tx/__tests__/txMonitor.test.ts | 6 +-
.../tx/tx-sender/__tests__/ts-sender.test.ts | 5 -
src/services/tx/tx-sender/dispatch.ts | 33 +-
src/services/tx/txMonitor.ts | 25 +-
src/utils/transactions.ts | 12 +-
7 files changed, 379 insertions(+), 44 deletions(-)
create mode 100644 src/hooks/__tests__/useTxPendingStatus.test.ts
diff --git a/src/hooks/__tests__/useTxPendingStatus.test.ts b/src/hooks/__tests__/useTxPendingStatus.test.ts
new file mode 100644
index 0000000000..a05ecb5320
--- /dev/null
+++ b/src/hooks/__tests__/useTxPendingStatus.test.ts
@@ -0,0 +1,337 @@
+import { txDispatch, TxEvent } from '@/services/tx/txEvents'
+import { extendedSafeInfoBuilder } from '@/tests/builders/safe'
+import { faker } from '@faker-js/faker'
+import type { JsonRpcProvider } from 'ethers'
+import * as useChainIdHook from '@/hooks/useChainId'
+import * as useSafeInfoHook from '@/hooks/useSafeInfo'
+import useTxPendingStatuses, { useTxMonitor } from '@/hooks/useTxPendingStatuses'
+import * as web3 from '@/hooks/wallets/web3'
+import * as txMonitor from '@/services/tx/txMonitor'
+import {
+ clearPendingTx,
+ PendingStatus,
+ type PendingTxsState,
+ PendingTxType,
+ setPendingTx,
+} from '@/store/pendingTxsSlice'
+import { renderHook } from '@/tests/test-utils'
+
+describe('useTxMonitor', () => {
+ let mockProvider
+ beforeEach(() => {
+ jest.clearAllMocks()
+
+ jest.spyOn(useChainIdHook, 'default').mockReturnValue('11155111')
+
+ mockProvider = jest.fn() as unknown as JsonRpcProvider
+ jest.spyOn(web3, 'useWeb3ReadOnly').mockReturnValue(mockProvider)
+ })
+
+ it('should not monitor transactions if provider is not available', () => {
+ jest.spyOn(web3, 'useWeb3ReadOnly').mockReturnValue(undefined)
+ const mockWaitForTx = jest.spyOn(txMonitor, 'waitForTx')
+ const mockWaitForRelayedTx = jest.spyOn(txMonitor, 'waitForRelayedTx')
+
+ renderHook(() => useTxMonitor())
+
+ expect(mockWaitForTx).not.toHaveBeenCalled()
+ expect(mockWaitForRelayedTx).not.toHaveBeenCalled()
+ })
+
+ it('should not monitor transactions if there are no pending transactions', () => {
+ const mockWaitForTx = jest.spyOn(txMonitor, 'waitForTx')
+ const mockWaitForRelayedTx = jest.spyOn(txMonitor, 'waitForRelayedTx')
+
+ renderHook(() => useTxMonitor, { initialReduxState: { pendingTxs: {} } })
+
+ expect(mockWaitForTx).not.toHaveBeenCalled()
+ expect(mockWaitForRelayedTx).not.toHaveBeenCalled()
+ })
+
+ it('should monitor processing transactions', () => {
+ const mockWaitForTx = jest.spyOn(txMonitor, 'waitForTx')
+ const mockWaitForRelayedTx = jest.spyOn(txMonitor, 'waitForRelayedTx')
+
+ const pendingTx: PendingTxsState = {
+ '123': {
+ chainId: '11155111',
+ safeAddress: faker.finance.ethereumAddress(),
+ status: PendingStatus.PROCESSING,
+ txHash: '0x456',
+ submittedAt: Date.now(),
+ signerNonce: 1,
+ signerAddress: faker.finance.ethereumAddress(),
+ txType: PendingTxType.SAFE_TX,
+ },
+ }
+
+ renderHook(() => useTxMonitor(), { initialReduxState: { pendingTxs: pendingTx } })
+
+ expect(mockWaitForTx).toHaveBeenCalled()
+ expect(mockWaitForRelayedTx).not.toHaveBeenCalled()
+ })
+
+ it('should monitor relaying transactions', () => {
+ const mockWaitForTx = jest.spyOn(txMonitor, 'waitForTx')
+ const mockWaitForRelayedTx = jest.spyOn(txMonitor, 'waitForRelayedTx')
+
+ const pendingTx: PendingTxsState = {
+ '123': {
+ chainId: '11155111',
+ safeAddress: faker.finance.ethereumAddress(),
+ status: PendingStatus.RELAYING,
+ taskId: '0x456',
+ },
+ }
+
+ renderHook(() => useTxMonitor(), { initialReduxState: { pendingTxs: pendingTx } })
+
+ expect(mockWaitForRelayedTx).toHaveBeenCalled()
+ expect(mockWaitForTx).not.toHaveBeenCalled()
+ })
+
+ it('should not monitor already monitored transactions', () => {
+ const mockWaitForTx = jest.spyOn(txMonitor, 'waitForTx')
+
+ const pendingTxs: PendingTxsState = {
+ '123': {
+ chainId: '11155111',
+ safeAddress: faker.finance.ethereumAddress(),
+ status: PendingStatus.PROCESSING,
+ txHash: '0x456',
+ submittedAt: Date.now(),
+ signerNonce: 1,
+ signerAddress: faker.finance.ethereumAddress(),
+ txType: PendingTxType.SAFE_TX,
+ },
+ }
+
+ const { rerender } = renderHook(() => useTxMonitor(), { initialReduxState: { pendingTxs } })
+
+ rerender()
+
+ expect(mockWaitForTx).toHaveBeenCalledTimes(1)
+ })
+})
+
+jest.mock('@/store/pendingTxsSlice', () => {
+ const original = jest.requireActual('@/store/pendingTxsSlice')
+ return {
+ ...original,
+ setPendingTx: jest.fn(original.setPendingTx),
+ clearPendingTx: jest.fn(original.clearPendingTx),
+ }
+})
+
+const extendedSafeInfo = extendedSafeInfoBuilder().build()
+
+describe('useTxPendingStatuses', () => {
+ beforeEach(() => {
+ jest.clearAllMocks()
+
+ jest.spyOn(useChainIdHook, 'default').mockReturnValue('11155111')
+ jest.spyOn(useSafeInfoHook, 'default').mockReturnValue({
+ safe: extendedSafeInfo,
+ safeAddress: faker.finance.ethereumAddress(),
+ safeError: undefined,
+ safeLoaded: true,
+ safeLoading: false,
+ })
+ })
+
+ it('should update pending tx when SIGNATURE_PROPOSED', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+ const mockSignerAddress = faker.finance.ethereumAddress()
+
+ txDispatch(TxEvent.SIGNATURE_PROPOSED, {
+ txId: mockTxId,
+ signerAddress: mockSignerAddress,
+ })
+
+ expect(setPendingTx).toHaveBeenCalledWith({
+ chainId: expect.anything(),
+ safeAddress: expect.anything(),
+ signerAddress: mockSignerAddress,
+ status: PendingStatus.SIGNING,
+ txId: mockTxId,
+ })
+ })
+
+ it('should update custom pending tx when PROCESSING', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+ const mockTxHash = '0x123'
+ const mockNonce = 1
+ const mockData = '0x456'
+ const mockSignerAddress = faker.finance.ethereumAddress()
+ const mockTo = faker.finance.ethereumAddress()
+
+ txDispatch(TxEvent.PROCESSING, {
+ txId: mockTxId,
+ txHash: mockTxHash,
+ signerNonce: mockNonce,
+ signerAddress: mockSignerAddress,
+ txType: 'Custom',
+ data: mockData,
+ to: mockTo,
+ })
+
+ expect(setPendingTx).toHaveBeenCalledWith({
+ chainId: expect.anything(),
+ safeAddress: expect.anything(),
+ submittedAt: expect.anything(),
+ signerAddress: mockSignerAddress,
+ signerNonce: mockNonce,
+ to: mockTo,
+ data: mockData,
+ status: PendingStatus.PROCESSING,
+ txId: mockTxId,
+ txHash: mockTxHash,
+ txType: PendingTxType.CUSTOM_TX,
+ })
+ })
+
+ it('should update pending safe tx when PROCESSING', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+ const mockTxHash = '0x123'
+ const mockNonce = 1
+ const mockGasLimit = '80000'
+ const mockSignerAddress = faker.finance.ethereumAddress()
+
+ txDispatch(TxEvent.PROCESSING, {
+ txId: mockTxId,
+ txHash: mockTxHash,
+ signerNonce: mockNonce,
+ signerAddress: mockSignerAddress,
+ txType: 'SafeTx',
+ gasLimit: mockGasLimit,
+ })
+
+ expect(setPendingTx).toHaveBeenCalledWith({
+ chainId: expect.anything(),
+ safeAddress: expect.anything(),
+ submittedAt: expect.anything(),
+ signerAddress: mockSignerAddress,
+ signerNonce: mockNonce,
+ gasLimit: mockGasLimit,
+ status: PendingStatus.PROCESSING,
+ txId: mockTxId,
+ txHash: mockTxHash,
+ txType: PendingTxType.SAFE_TX,
+ })
+ })
+
+ it('should update pending tx when EXECUTING', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+
+ txDispatch(TxEvent.EXECUTING, {
+ txId: mockTxId,
+ })
+
+ expect(setPendingTx).toHaveBeenCalledWith({
+ chainId: expect.anything(),
+ safeAddress: expect.anything(),
+ status: PendingStatus.SUBMITTING,
+ txId: mockTxId,
+ })
+ })
+
+ it('should update pending tx when PROCESSED', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+
+ txDispatch(TxEvent.PROCESSED, {
+ txId: mockTxId,
+ safeAddress: faker.finance.ethereumAddress(),
+ })
+
+ expect(setPendingTx).toHaveBeenCalledWith({
+ chainId: expect.anything(),
+ safeAddress: expect.anything(),
+ status: PendingStatus.INDEXING,
+ txId: mockTxId,
+ })
+ })
+
+ it('should update pending tx when RELAYING', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+ const mockTaskId = '0x123'
+
+ txDispatch(TxEvent.RELAYING, {
+ txId: mockTxId,
+ taskId: mockTaskId,
+ })
+
+ expect(setPendingTx).toHaveBeenCalledWith({
+ chainId: expect.anything(),
+ safeAddress: expect.anything(),
+ status: PendingStatus.RELAYING,
+ txId: mockTxId,
+ taskId: mockTaskId,
+ })
+ })
+
+ it('should clear the pending tx on SUCCESS', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+
+ txDispatch(TxEvent.SUCCESS, {
+ txId: mockTxId,
+ })
+
+ expect(setPendingTx).not.toHaveBeenCalled()
+ expect(clearPendingTx).toHaveBeenCalled()
+ })
+
+ it('should clear the pending tx on SIGNATURE_INDEXED', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+
+ txDispatch(TxEvent.SIGNATURE_INDEXED, {
+ txId: mockTxId,
+ })
+
+ expect(setPendingTx).not.toHaveBeenCalled()
+ expect(clearPendingTx).toHaveBeenCalled()
+ })
+
+ it('should clear the pending tx on REVERTED', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+
+ txDispatch(TxEvent.REVERTED, {
+ txId: mockTxId,
+ error: new Error('Transaction reverted'),
+ })
+
+ expect(setPendingTx).not.toHaveBeenCalled()
+ expect(clearPendingTx).toHaveBeenCalled()
+ })
+
+ it('should clear the pending tx on FAILED', () => {
+ renderHook(() => useTxPendingStatuses())
+
+ const mockTxId = '123'
+
+ txDispatch(TxEvent.FAILED, {
+ txId: mockTxId,
+ error: new Error('Transaction failed'),
+ })
+
+ expect(setPendingTx).not.toHaveBeenCalled()
+ expect(clearPendingTx).toHaveBeenCalled()
+ })
+})
diff --git a/src/hooks/useTxPendingStatuses.ts b/src/hooks/useTxPendingStatuses.ts
index aaffbe7613..720bf71d81 100644
--- a/src/hooks/useTxPendingStatuses.ts
+++ b/src/hooks/useTxPendingStatuses.ts
@@ -19,7 +19,7 @@ import { SimpleTxWatcher } from '@/utils/SimpleTxWatcher'
const FINAL_PENDING_STATUSES = [TxEvent.SIGNATURE_INDEXED, TxEvent.SUCCESS, TxEvent.REVERTED, TxEvent.FAILED]
-const useTxMonitor = (): void => {
+export const useTxMonitor = (): void => {
const chainId = useChainId()
const pendingTxs = useAppSelector(selectPendingTxs)
const pendingTxEntriesOnChain = Object.entries(pendingTxs).filter(([, pendingTx]) => pendingTx.chainId === chainId)
@@ -53,6 +53,7 @@ const useTxMonitor = (): void => {
pendingTx.safeAddress,
pendingTx.signerAddress,
pendingTx.signerNonce,
+ chainId,
)
continue
}
@@ -63,7 +64,7 @@ const useTxMonitor = (): void => {
}
// `provider` is updated when switching chains, re-running this effect
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [provider])
+ }, [pendingTxEntriesOnChain.length, provider])
}
const useTxPendingStatuses = (): void => {
diff --git a/src/services/tx/__tests__/txMonitor.test.ts b/src/services/tx/__tests__/txMonitor.test.ts
index cc46409c63..789a60bda7 100644
--- a/src/services/tx/__tests__/txMonitor.test.ts
+++ b/src/services/tx/__tests__/txMonitor.test.ts
@@ -47,7 +47,7 @@ describe('txMonitor', () => {
// https://docs.ethers.io/v5/single-page/#/v5/api/providers/provider/-%23-Provider-waitForTransaction
const receipt = null as unknown as TransactionReceipt
watchTxHashSpy.mockImplementation(() => Promise.resolve(receipt))
- await waitForTx(provider, ['0x0'], '0x0', safeAddress, faker.finance.ethereumAddress(), 1)
+ await waitForTx(provider, ['0x0'], '0x0', safeAddress, faker.finance.ethereumAddress(), 1, '11155111')
expect(txDispatchSpy).toHaveBeenCalledWith('FAILED', { txId: '0x0', error: expect.any(Error) })
})
@@ -58,7 +58,7 @@ describe('txMonitor', () => {
} as TransactionReceipt
watchTxHashSpy.mockImplementation(() => Promise.resolve(receipt))
- await waitForTx(provider, ['0x0'], '0x0', safeAddress, faker.finance.ethereumAddress(), 1)
+ await waitForTx(provider, ['0x0'], '0x0', safeAddress, faker.finance.ethereumAddress(), 1, '11155111')
expect(txDispatchSpy).toHaveBeenCalledWith('REVERTED', {
txId: '0x0',
@@ -68,7 +68,7 @@ describe('txMonitor', () => {
it('emits a FAILED event if waitForTransaction throws', async () => {
watchTxHashSpy.mockImplementation(() => Promise.reject(new Error('Test error.')))
- await waitForTx(provider, ['0x0'], '0x0', safeAddress, faker.finance.ethereumAddress(), 1)
+ await waitForTx(provider, ['0x0'], '0x0', safeAddress, faker.finance.ethereumAddress(), 1, '11155111')
expect(txDispatchSpy).toHaveBeenCalledWith('FAILED', { txId: '0x0', error: new Error('Test error.') })
})
diff --git a/src/services/tx/tx-sender/__tests__/ts-sender.test.ts b/src/services/tx/tx-sender/__tests__/ts-sender.test.ts
index 4dc35facba..c8bc97ba77 100644
--- a/src/services/tx/tx-sender/__tests__/ts-sender.test.ts
+++ b/src/services/tx/tx-sender/__tests__/ts-sender.test.ts
@@ -454,7 +454,6 @@ describe('txSender', () => {
gasLimit: undefined,
txType: 'SafeTx',
})
- expect(txEvents.txDispatch).toHaveBeenCalledWith('PROCESSED', { txId, safeAddress, txHash: TX_HASH })
})
it('should fail executing a tx', async () => {
@@ -503,10 +502,6 @@ describe('txSender', () => {
txType: 'SafeTx',
gasLimit: undefined,
})
- expect(txEvents.txDispatch).toHaveBeenCalledWith('REVERTED', {
- txId,
- error: new Error('Transaction reverted by EVM.'),
- })
})
})
diff --git a/src/services/tx/tx-sender/dispatch.ts b/src/services/tx/tx-sender/dispatch.ts
index d28f22f127..55d6294932 100644
--- a/src/services/tx/tx-sender/dispatch.ts
+++ b/src/services/tx/tx-sender/dispatch.ts
@@ -21,7 +21,7 @@ import type { ContractTransactionResponse, Eip1193Provider, Overrides, Transacti
import type { RequestId } from '@safe-global/safe-apps-sdk'
import proposeTx from '../proposeTransaction'
import { txDispatch, TxEvent } from '../txEvents'
-import { waitForRelayedTx, waitForTx } from '@/services/tx/txMonitor'
+import { waitForRelayedTx } from '@/services/tx/txMonitor'
import { getReadOnlyCurrentGnosisSafeContract } from '@/services/contracts/safeContracts'
import {
getAndValidateSafeSDK,
@@ -31,7 +31,7 @@ import {
prepareTxExecution,
prepareApproveTxHash,
} from './sdk'
-import { createWeb3, getUserNonce, getWeb3ReadOnly } from '@/hooks/wallets/web3'
+import { createWeb3, getUserNonce } from '@/hooks/wallets/web3'
import { asError } from '@/services/exceptions/utils'
import chains from '@/config/chains'
import { createExistingTx } from './create'
@@ -215,13 +215,6 @@ export const dispatchSafeTxSpeedUp = async (
txType: 'SafeTx',
})
- const readOnlyProvider = getWeb3ReadOnly()
-
- if (readOnlyProvider) {
- // don't await as we don't want to block
- waitForTx(readOnlyProvider, [txId], result.hash, safeAddress, signerAddress, signerNonce)
- }
-
return result.hash
}
@@ -258,13 +251,6 @@ export const dispatchCustomTxSpeedUp = async (
txType: 'Custom',
})
- const readOnlyProvider = getWeb3ReadOnly()
-
- if (readOnlyProvider) {
- // don't await as we don't want to block
- waitForTx(readOnlyProvider, [txId], result.hash, safeAddress, signerAddress, signerNonce)
- }
-
return result.hash
}
@@ -318,14 +304,6 @@ export const dispatchTxExecution = async (
txType: 'SafeTx',
})
- const readOnlyProvider = getWeb3ReadOnly()
-
- // Asynchronously watch the tx to be mined/validated
- if (readOnlyProvider) {
- // don't await as we don't want to block
- waitForTx(readOnlyProvider, [txId], result.hash, safeAddress, signerAddress, signerNonce)
- }
-
return result.hash
}
@@ -377,13 +355,6 @@ export const dispatchBatchExecution = async (
})
})
- const readOnlyProvider = getWeb3ReadOnly()
-
- if (readOnlyProvider) {
- // don't await as we don't want to block
- waitForTx(readOnlyProvider, txIds, result.hash, safeAddress, signerAddress, signerNonce)
- }
-
return result!.hash
}
diff --git a/src/services/tx/txMonitor.ts b/src/services/tx/txMonitor.ts
index 2931808128..d3affefccb 100644
--- a/src/services/tx/txMonitor.ts
+++ b/src/services/tx/txMonitor.ts
@@ -4,6 +4,7 @@ import { txDispatch, TxEvent } from '@/services/tx/txEvents'
import { POLLING_INTERVAL } from '@/config/constants'
import { Errors, logError } from '@/services/exceptions'
+import { getSafeTransaction } from '@/utils/transactions'
import { asError } from '../exceptions/utils'
import { type JsonRpcProvider, type TransactionReceipt } from 'ethers'
import { SimpleTxWatcher } from '@/utils/SimpleTxWatcher'
@@ -23,6 +24,7 @@ export const waitForTx = async (
safeAddress: string,
walletAddress: string,
walletNonce: number,
+ chainId: string,
) => {
const processReceipt = (receipt: TransactionReceipt | null, txIds: string[]) => {
if (receipt === null) {
@@ -62,8 +64,27 @@ export const waitForTx = async (
}
try {
- const receipt = await SimpleTxWatcher.getInstance().watchTxHash(txHash, walletAddress, walletNonce, provider)
- processReceipt(receipt, txIds)
+ const isSafeTx = !!(await getSafeTransaction(txHash, chainId, safeAddress))
+ if (isSafeTx) {
+ // Poll for the transaction until it has a transactionHash and start the watcher
+ const interval = setInterval(async () => {
+ const safeTx = await getSafeTransaction(txHash, chainId, safeAddress)
+ if (!safeTx?.txHash) return
+
+ clearInterval(interval)
+
+ const receipt = await SimpleTxWatcher.getInstance().watchTxHash(
+ safeTx.txHash,
+ walletAddress,
+ walletNonce,
+ provider,
+ )
+ processReceipt(receipt, txIds)
+ }, POLLING_INTERVAL)
+ } else {
+ const receipt = await SimpleTxWatcher.getInstance().watchTxHash(txHash, walletAddress, walletNonce, provider)
+ processReceipt(receipt, txIds)
+ }
} catch (error) {
processError(error, txIds)
}
diff --git a/src/utils/transactions.ts b/src/utils/transactions.ts
index a9fc0af7f0..a3e151e739 100644
--- a/src/utils/transactions.ts
+++ b/src/utils/transactions.ts
@@ -10,7 +10,7 @@ import type {
TransactionListPage,
TransactionSummary,
} from '@safe-global/safe-gateway-typescript-sdk'
-import { ConflictType, TransactionListItemType } from '@safe-global/safe-gateway-typescript-sdk'
+import { ConflictType, getTransactionDetails, TransactionListItemType } from '@safe-global/safe-gateway-typescript-sdk'
import {
isERC20Transfer,
isModuleDetailedExecutionInfo,
@@ -295,3 +295,13 @@ export const isTrustedTx = (tx: TransactionSummary) => {
export const isImitation = ({ txInfo }: TransactionSummary): boolean => {
return isTransferTxInfo(txInfo) && isERC20Transfer(txInfo.transferInfo) && Boolean(txInfo.transferInfo.imitation)
}
+
+export const getSafeTransaction = async (safeTxHash: string, chainId: string, safeAddress: string) => {
+ const txId = `multisig_${safeAddress}_${safeTxHash}`
+
+ try {
+ return await getTransactionDetails(chainId, txId)
+ } catch (e) {
+ return undefined
+ }
+}
From 1832193802df5e7e162f466a0140c33d79e66b4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=B3vis=20Neto?=
Date: Tue, 10 Sep 2024 09:46:15 +0200
Subject: [PATCH 52/81] Highlight raw data transactions (#4146)
* fix: Only highlight Data (hex-encoded)
* chore: Create unit tests to increase component coverage
---
.../HexEncodedData/HexEncodedData.test.tsx | 39 ++++
.../HexEncodedData.test.tsx.snap | 187 ++++++++++++++++++
.../transactions/HexEncodedData/index.tsx | 17 +-
.../TxDetails/Summary/TxDataRow/index.tsx | 2 +-
.../TxData/DecodedData/ValueArray/index.tsx | 2 +-
5 files changed, 240 insertions(+), 7 deletions(-)
create mode 100644 src/components/transactions/HexEncodedData/HexEncodedData.test.tsx
create mode 100644 src/components/transactions/HexEncodedData/__snapshots__/HexEncodedData.test.tsx.snap
diff --git a/src/components/transactions/HexEncodedData/HexEncodedData.test.tsx b/src/components/transactions/HexEncodedData/HexEncodedData.test.tsx
new file mode 100644
index 0000000000..6aa788bcd7
--- /dev/null
+++ b/src/components/transactions/HexEncodedData/HexEncodedData.test.tsx
@@ -0,0 +1,39 @@
+import { render } from '@/tests/test-utils'
+import { HexEncodedData } from '.'
+
+const hexData = '0xed2ad31ed00088fc64d00c49774b2fe3fb7fd7db1c2a714700892607b9f77dc1'
+
+describe('HexEncodedData', () => {
+ it('should render the default component markup', () => {
+ const result = render( )
+ const showMoreButton = result.getByTestId('show-more')
+ const tooltipComponent = result.getByLabelText(
+ 'The first 4 bytes determine the contract method that is being called',
+ )
+ const copyButton = result.getByTestId('copy-btn-icon')
+
+ expect(showMoreButton).toBeInTheDocument()
+ expect(showMoreButton).toHaveTextContent('Show more')
+ expect(tooltipComponent).toBeInTheDocument()
+ expect(copyButton).toBeInTheDocument()
+
+ expect(result.container).toMatchSnapshot()
+ })
+
+ it('should not highlight the data if highlight option is false', () => {
+ const result = render(
+ ,
+ )
+
+ expect(result.container.querySelector('b')).not.toBeInTheDocument()
+ expect(result.container).toMatchSnapshot()
+ })
+
+ it('should not cut the text in case the limit option is higher than the provided hexData', () => {
+ const result = render( )
+
+ expect(result.container.querySelector("button[data-testid='show-more']")).not.toBeInTheDocument()
+
+ expect(result.container).toMatchSnapshot()
+ })
+})
diff --git a/src/components/transactions/HexEncodedData/__snapshots__/HexEncodedData.test.tsx.snap b/src/components/transactions/HexEncodedData/__snapshots__/HexEncodedData.test.tsx.snap
new file mode 100644
index 0000000000..bf3739bfc5
--- /dev/null
+++ b/src/components/transactions/HexEncodedData/__snapshots__/HexEncodedData.test.tsx.snap
@@ -0,0 +1,187 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`HexEncodedData should not cut the text in case the limit option is higher than the provided hexData 1`] = `
+
+
+
+
+ Data (hex-encoded)
+
+
+
+
+
+
+
+
+
+
+
+ 0xed2ad31e
+
+ d00088fc64d00c49774b2fe3fb7fd7db1c2a714700892607b9f77dc1
+
+
+
+
+
+`;
+
+exports[`HexEncodedData should not highlight the data if highlight option is false 1`] = `
+
+
+
+
+ Some arbitrary data
+
+
+
+
+
+
+
+
+
+
+ 0x10238476...
+
+
+ Show
+ more
+
+
+
+
+
+`;
+
+exports[`HexEncodedData should render the default component markup 1`] = `
+
+
+
+
+ Data (hex-encoded)
+
+
+
+
+
+
+
+
+
+
+
+ 0xed2ad31e
+
+ d00088fc64...
+
+
+ Show
+ more
+
+
+
+
+
+`;
diff --git a/src/components/transactions/HexEncodedData/index.tsx b/src/components/transactions/HexEncodedData/index.tsx
index 5b54aca3ed..fe635c5dcf 100644
--- a/src/components/transactions/HexEncodedData/index.tsx
+++ b/src/components/transactions/HexEncodedData/index.tsx
@@ -8,13 +8,14 @@ import FieldsGrid from '@/components/tx/FieldsGrid'
interface Props {
hexData: string
+ highlightFirstBytes?: boolean
title?: string
limit?: number
}
const FIRST_BYTES = 10
-export const HexEncodedData = ({ hexData, title, limit = 20 }: Props): ReactElement => {
+export const HexEncodedData = ({ hexData, title, highlightFirstBytes = true, limit = 20 }: Props): ReactElement => {
const [showTxData, setShowTxData] = useState(false)
const showExpandBtn = hexData.length > limit
@@ -22,12 +23,12 @@ export const HexEncodedData = ({ hexData, title, limit = 20 }: Props): ReactElem
setShowTxData((val) => !val)
}
- const firstBytes = (
+ const firstBytes = highlightFirstBytes ? (
{hexData.slice(0, FIRST_BYTES)}
- )
- const restBytes = hexData.slice(FIRST_BYTES)
+ ) : null
+ const restBytes = highlightFirstBytes ? hexData.slice(FIRST_BYTES) : hexData
const content = (
@@ -37,7 +38,13 @@ export const HexEncodedData = ({ hexData, title, limit = 20 }: Props): ReactElem
{firstBytes}
{showTxData || !showExpandBtn ? restBytes : shortenText(restBytes, limit - FIRST_BYTES)}{' '}
{showExpandBtn && (
-
+
Show {showTxData ? 'less' : 'more'}
)}
diff --git a/src/components/transactions/TxDetails/Summary/TxDataRow/index.tsx b/src/components/transactions/TxDetails/Summary/TxDataRow/index.tsx
index cba0c13711..f0b68a02b2 100644
--- a/src/components/transactions/TxDetails/Summary/TxDataRow/index.tsx
+++ b/src/components/transactions/TxDetails/Summary/TxDataRow/index.tsx
@@ -40,7 +40,7 @@ export const generateDataRowValue = (
)
case 'bytes':
- return
+ return
default:
return {value}
}
diff --git a/src/components/transactions/TxDetails/TxData/DecodedData/ValueArray/index.tsx b/src/components/transactions/TxDetails/TxData/DecodedData/ValueArray/index.tsx
index 408aa7b40a..8bc19b7cf5 100644
--- a/src/components/transactions/TxDetails/TxData/DecodedData/ValueArray/index.tsx
+++ b/src/components/transactions/TxDetails/TxData/DecodedData/ValueArray/index.tsx
@@ -62,7 +62,7 @@ export const Value = ({ type, value, ...props }: ValueArrayProps): ReactElement
}
const getTextValue = (value: string, key?: string) => {
- return
+ return
}
const getArrayValue = (parentId: string, value: string[], separator?: boolean) => (
From 69e4992446b582b9502d3faafa86eb393061265b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=B3vis=20Neto?=
Date: Tue, 10 Sep 2024 09:47:59 +0200
Subject: [PATCH 53/81] fix: Consider app category in the searchbar query
filter (#4147)
---
src/hooks/safe-apps/useAppsSearch.ts | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/hooks/safe-apps/useAppsSearch.ts b/src/hooks/safe-apps/useAppsSearch.ts
index f2f57ad413..900b8e18ef 100644
--- a/src/hooks/safe-apps/useAppsSearch.ts
+++ b/src/hooks/safe-apps/useAppsSearch.ts
@@ -15,6 +15,10 @@ const useAppsSearch = (apps: SafeAppData[], query: string): SafeAppData[] => {
name: 'description',
weight: 0.5,
},
+ {
+ name: 'tags',
+ weight: 0.99,
+ },
],
// https://fusejs.io/api/options.html#threshold
// Very naive explanation: threshold represents how accurate the search results should be. The default is 0.6
From f0d5530628205b478738e6a85f81596b257f389c Mon Sep 17 00:00:00 2001
From: Manuel Gellfart
Date: Tue, 10 Sep 2024 10:41:39 +0200
Subject: [PATCH 54/81] feat: show Safe{Pass} points in header (#4064)
---
jest.setup.js | 2 +-
public/images/common/safe-pass-star.svg | 10 +++
.../__tests__/SafeTokenWidget.test.tsx | 45 ++++++----
.../common/SafeTokenWidget/index.tsx | 89 ++++++++++---------
src/store/index.ts | 3 +
src/store/safePass.ts | 37 ++++++++
6 files changed, 127 insertions(+), 59 deletions(-)
create mode 100644 public/images/common/safe-pass-star.svg
create mode 100644 src/store/safePass.ts
diff --git a/jest.setup.js b/jest.setup.js
index 702bee6130..3a44ca67c0 100644
--- a/jest.setup.js
+++ b/jest.setup.js
@@ -43,7 +43,7 @@ const NumberFormat = Intl.NumberFormat
const englishTestLocale = 'en'
// `viem` used by the `safe-apps-sdk` uses `TextEncoder` and `TextDecoder` which are not available in jsdom for some reason
-Object.assign(global, { TextDecoder, TextEncoder })
+Object.assign(global, { TextDecoder, TextEncoder, fetch: jest.fn() })
jest.spyOn(Intl, 'NumberFormat').mockImplementation((locale, ...rest) => new NumberFormat([englishTestLocale], ...rest))
diff --git a/public/images/common/safe-pass-star.svg b/public/images/common/safe-pass-star.svg
new file mode 100644
index 0000000000..2cff53958a
--- /dev/null
+++ b/public/images/common/safe-pass-star.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/common/SafeTokenWidget/__tests__/SafeTokenWidget.test.tsx b/src/components/common/SafeTokenWidget/__tests__/SafeTokenWidget.test.tsx
index 49090fab72..b92a675f2e 100644
--- a/src/components/common/SafeTokenWidget/__tests__/SafeTokenWidget.test.tsx
+++ b/src/components/common/SafeTokenWidget/__tests__/SafeTokenWidget.test.tsx
@@ -5,8 +5,10 @@ import SafeTokenWidget from '..'
import { toBeHex } from 'ethers'
import { AppRoutes } from '@/config/routes'
import useSafeTokenAllocation, { useSafeVotingPower } from '@/hooks/useSafeTokenAllocation'
+import * as safePass from '@/store/safePass'
+import type { CampaignLeaderboardEntry } from '@/store/safePass'
-jest.mock('@/hooks/useChainId', () => jest.fn(() => '1'))
+jest.mock('@/hooks/useChainId')
jest.mock('@/hooks/useSafeTokenAllocation')
@@ -20,10 +22,17 @@ describe('SafeTokenWidget', () => {
get: () => fakeSafeAddress,
} as any),
)
+
+ jest.spyOn(safePass, 'useGetOwnGlobalCampaignRankQuery').mockReturnValue({
+ data: undefined,
+ isLoading: false,
+ refetch: jest.fn(),
+ })
+ ;(useChainId as jest.Mock).mockImplementation(jest.fn(() => '1'))
})
it('Should render nothing for unsupported chains', () => {
- ;(useChainId as jest.Mock).mockImplementationOnce(jest.fn(() => '100'))
+ ;(useChainId as jest.Mock).mockImplementation(jest.fn(() => '100'))
;(useSafeTokenAllocation as jest.Mock).mockImplementation(() => [[], , false])
;(useSafeVotingPower as jest.Mock).mockImplementation(() => [BigInt(0), , false])
@@ -43,16 +52,10 @@ describe('SafeTokenWidget', () => {
;(useSafeTokenAllocation as jest.Mock).mockImplementation(() => [[], , false])
;(useSafeVotingPower as jest.Mock).mockImplementation(() => [BigInt('472238796133701648384'), , false])
- // to avoid failing tests in some environments
- const NumberFormat = Intl.NumberFormat
- const englishTestLocale = 'en'
-
- jest.spyOn(Intl, 'NumberFormat').mockImplementation((_, ...rest) => new NumberFormat([englishTestLocale], ...rest))
-
const result = render( )
await waitFor(() => {
- expect(result.baseElement).toHaveTextContent('472.24')
- expect(result.baseElement).not.toHaveTextContent('472.2388')
+ expect(result.baseElement).toHaveTextContent('472')
+ expect(result.baseElement).not.toHaveTextContent('472.2')
})
})
@@ -70,13 +73,25 @@ describe('SafeTokenWidget', () => {
})
})
- it('Should render a claim button for SEP5 qualification', async () => {
- ;(useSafeTokenAllocation as jest.Mock).mockImplementation(() => [[{ tag: 'user_v2' }], , false])
- ;(useSafeVotingPower as jest.Mock).mockImplementation(() => [BigInt(420000), , false])
-
+ it('Should render the Safe{Pass} points', async () => {
+ ;(useSafeTokenAllocation as jest.Mock).mockImplementation(() => [[], , false])
+ ;(useSafeVotingPower as jest.Mock).mockImplementation(() => [BigInt(420 * 10 ** 18), , false])
+ const mockCampaignRank: CampaignLeaderboardEntry = {
+ boost: '2.0',
+ holder: fakeSafeAddress,
+ position: 421,
+ totalBoostedPoints: 138,
+ totalPoints: 69,
+ }
+ jest.spyOn(safePass, 'useGetOwnGlobalCampaignRankQuery').mockReturnValue({
+ data: mockCampaignRank,
+ isLoading: false,
+ refetch: jest.fn(),
+ })
const result = render( )
await waitFor(() => {
- expect(result.baseElement).toContainHTML('New allocation')
+ expect(result.queryByText('420')).toBeInTheDocument() // Safe Voting power
+ expect(result.queryByText('138')).toBeInTheDocument() // Safe Pass points
})
})
})
diff --git a/src/components/common/SafeTokenWidget/index.tsx b/src/components/common/SafeTokenWidget/index.tsx
index 79c4aa10fb..ee8a9869d1 100644
--- a/src/components/common/SafeTokenWidget/index.tsx
+++ b/src/components/common/SafeTokenWidget/index.tsx
@@ -1,17 +1,21 @@
import { IS_PRODUCTION, SAFE_TOKEN_ADDRESSES, SAFE_LOCKING_ADDRESS } from '@/config/constants'
import { AppRoutes } from '@/config/routes'
import useChainId from '@/hooks/useChainId'
-import useSafeTokenAllocation, { useSafeVotingPower, type Vesting } from '@/hooks/useSafeTokenAllocation'
+import useSafeTokenAllocation, { useSafeVotingPower } from '@/hooks/useSafeTokenAllocation'
import { OVERVIEW_EVENTS } from '@/services/analytics'
import { formatVisualAmount } from '@/utils/formatters'
-import { Box, Button, ButtonBase, Skeleton, Tooltip, Typography } from '@mui/material'
+import { Box, ButtonBase, Divider, Skeleton, SvgIcon, Tooltip, Typography } from '@mui/material'
import Link from 'next/link'
import { useSearchParams } from 'next/navigation'
import Track from '../Track'
import SafeTokenIcon from '@/public/images/common/safe-token.svg'
+import SafePassStar from '@/public/images/common/safe-pass-star.svg'
import css from './styles.module.css'
-import UnreadBadge from '../UnreadBadge'
-import classnames from 'classnames'
+import useSafeAddress from '@/hooks/useSafeAddress'
+import { skipToken } from '@reduxjs/toolkit/query/react'
+import { useDarkMode } from '@/hooks/useDarkMode'
+import { useGetOwnGlobalCampaignRankQuery } from '@/store/safePass'
+import { formatAmount } from '@/utils/formatNumber'
const TOKEN_DECIMALS = 18
@@ -28,25 +32,22 @@ export const getSafeLockingAddress = (chainId: string): string | undefined => {
return SAFE_LOCKING_ADDRESS[chainId]
}
-const canRedeemSep5Airdrop = (allocation?: Vesting[]): boolean => {
- const sep5Allocation = allocation?.find(({ tag }) => tag === 'user_v2')
-
- if (!sep5Allocation) {
- return false
- }
-
- return !sep5Allocation.isRedeemed && !sep5Allocation.isExpired
-}
-
const GOVERNANCE_APP_URL = IS_PRODUCTION ? 'https://community.safe.global' : 'https://safe-dao-governance.dev.5afe.dev'
const SafeTokenWidget = () => {
const chainId = useChainId()
+ const safeAddress = useSafeAddress()
const query = useSearchParams()
+ const darkMode = useDarkMode()
const [allocationData, , allocationDataLoading] = useSafeTokenAllocation()
const [allocation, , allocationLoading] = useSafeVotingPower(allocationData)
+ const { data: ownGlobalRank, isLoading: ownGlobalRankLoading } = useGetOwnGlobalCampaignRankQuery(
+ chainId !== '1' && chainId !== '11155111' ? skipToken : { chainId, safeAddress },
+ { refetchOnFocus: false },
+ )
+
const tokenAddress = getSafeTokenAddress(chainId)
if (!tokenAddress) {
return null
@@ -57,8 +58,7 @@ const SafeTokenWidget = () => {
query: { safe: query?.get('safe'), appUrl: GOVERNANCE_APP_URL },
}
- const canRedeemSep5 = canRedeemSep5Airdrop(allocationData)
- const flooredSafeBalance = formatVisualAmount(allocation || BigInt(0), TOKEN_DECIMALS, 2)
+ const flooredSafeBalance = formatVisualAmount(allocation || BigInt(0), TOKEN_DECIMALS, 0)
return (
@@ -66,40 +66,43 @@ const SafeTokenWidget = () => {
-
+
+ {allocationDataLoading || allocationLoading ? (
+
+ ) : (
+ flooredSafeBalance
+ )}
+
+
+
+
+
-
- {allocationDataLoading || allocationLoading ? (
-
- ) : (
- flooredSafeBalance
- )}
-
+ {ownGlobalRankLoading ? (
+
+ ) : (
+ formatAmount(Math.floor(ownGlobalRank?.totalBoostedPoints ?? 0), 0)
+ )}
- {canRedeemSep5 && (
-
-
- New allocation
-
-
- )}
diff --git a/src/store/index.ts b/src/store/index.ts
index 7ac81800a5..f1b02b21cd 100644
--- a/src/store/index.ts
+++ b/src/store/index.ts
@@ -23,6 +23,7 @@ import {
import * as slices from './slices'
import * as hydrate from './useHydrateStore'
import { ofacApi } from '@/store/ofac'
+import { safePassApi } from './safePass'
const rootReducer = combineReducers({
[slices.chainsSlice.name]: slices.chainsSlice.reducer,
@@ -47,6 +48,7 @@ const rootReducer = combineReducers({
[slices.undeployedSafesSlice.name]: slices.undeployedSafesSlice.reducer,
[slices.swapParamsSlice.name]: slices.swapParamsSlice.reducer,
[ofacApi.reducerPath]: ofacApi.reducer,
+ [safePassApi.reducerPath]: safePassApi.reducer,
[slices.gatewayApi.reducerPath]: slices.gatewayApi.reducer,
})
@@ -76,6 +78,7 @@ const middleware: Middleware<{}, RootState>[] = [
broadcastState(persistedSlices),
listenerMiddlewareInstance.middleware,
ofacApi.middleware,
+ safePassApi.middleware,
slices.gatewayApi.middleware,
]
const listeners = [safeMessagesListener, txHistoryListener, txQueueListener, swapOrderListener, swapOrderStatusListener]
diff --git a/src/store/safePass.ts b/src/store/safePass.ts
new file mode 100644
index 0000000000..875c44f9f3
--- /dev/null
+++ b/src/store/safePass.ts
@@ -0,0 +1,37 @@
+import { cgwDebugStorage } from '@/components/sidebar/DebugToggle'
+import { IS_PRODUCTION, GATEWAY_URL_PRODUCTION, GATEWAY_URL_STAGING } from '@/config/constants'
+import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'
+
+// TODO: Replace this with the auto-generated SDK once available.
+const GATEWAY_URL = IS_PRODUCTION || cgwDebugStorage.get() ? GATEWAY_URL_PRODUCTION : GATEWAY_URL_STAGING
+const GLOBAL_CAMPAIGN_IDS: Record<'1' | '11155111', string> = {
+ '11155111': 'fa9f462b-8e8c-4122-aa41-2464e919b721',
+ '1': '9ed78b8b-178d-4e25-9ef2-1517865991ee',
+}
+
+export type CampaignLeaderboardEntry = {
+ holder: string
+ position: number
+ boost: string
+ totalPoints: number
+ totalBoostedPoints: number
+}
+
+export const safePassApi = createApi({
+ reducerPath: 'safePassApi',
+ baseQuery: fetchBaseQuery({ baseUrl: GATEWAY_URL }),
+ endpoints: (builder) => ({
+ getOwnGlobalCampaignRank: builder.query<
+ CampaignLeaderboardEntry,
+ { chainId: '1' | '11155111'; safeAddress: string }
+ >({
+ query: (request) => ({
+ url: `v1/community/campaigns/${GLOBAL_CAMPAIGN_IDS[request.chainId]}/leaderboard/${request.safeAddress}`,
+ }),
+ }),
+ }),
+})
+
+// Export hooks for usage in functional components, which are
+// auto-generated based on the defined endpoints
+export const { useGetOwnGlobalCampaignRankQuery } = safePassApi
From 3cb5f575dd7480c7b7572d46236ca9fd2c10f9eb Mon Sep 17 00:00:00 2001
From: James Mealy
Date: Tue, 10 Sep 2024 11:55:51 +0200
Subject: [PATCH 55/81] Feat: display a Network switch button when connected on
the wrong chain (#4027)
* feat: add nwtwork check to CheckWallet component
* add missing network checks
* Add network switch button for notifications settings toggle
lint
remove wrong chain warning
remove commented code .
* tests: add unit test for new state in CheckWallet
* remove calls to assertwalletchain
* Dont check the network if button is disabled
* restore WrongChainWarning
* add WrongChainWarning to CF activation screen
* show network logo, align text styles, rename NetworkFee prop
* Use network warning with switch network button, and disable CTA when on wrong network
* remove unused WrongChainWarning component
* fix: update unit tests for network warnings
* fix: disable delegate propose button when on wrong network
---
src/components/common/ChainSwitcher/index.tsx | 45 +++++++++++++++----
.../common/CheckWallet/index.test.tsx | 22 ++++++++-
src/components/common/CheckWallet/index.tsx | 16 +++++--
.../new-safe/create/NetworkWarning/index.tsx | 12 ++---
.../create/steps/ReviewStep/index.test.tsx | 2 +-
.../create/steps/ReviewStep/index.tsx | 12 ++---
.../create/steps/ReviewStep/styles.module.css | 2 +-
.../create/steps/SetNameStep/index.tsx | 5 ++-
.../settings/PushNotifications/index.tsx | 21 ++++-----
.../transactions/ExecuteTxButton/index.tsx | 2 +-
.../transactions/SignTxButton/index.tsx | 2 +-
.../tx-flow/common/TxLayout/index.tsx | 2 +-
.../tx-flow/common/TxLayout/styles.module.css | 2 +-
.../flows/ExecuteBatch/ReviewBatch.tsx | 9 ++--
.../RecoverAccountFlowReview.tsx | 9 ++--
.../flows/SafeAppsTx/ReviewSafeAppsTx.tsx | 2 -
.../flows/SignMessage/SignMessage.test.tsx | 12 ++---
.../tx-flow/flows/SignMessage/SignMessage.tsx | 15 ++++---
.../ReviewSignMessageOnChain.tsx | 2 -
.../TokenTransfer/ReviewSpendingLimitTx.tsx | 17 ++++---
.../tx/SignOrExecuteForm/DelegateForm.tsx | 2 +-
.../tx/SignOrExecuteForm/ExecuteForm.tsx | 2 +-
.../ExecuteThroughRoleForm/index.tsx | 5 +--
.../tx/SignOrExecuteForm/SignForm.tsx | 2 +-
src/components/tx/SignOrExecuteForm/hooks.ts | 7 ---
src/components/tx/SignOrExecuteForm/index.tsx | 4 +-
src/components/tx/WrongChainWarning/index.tsx | 21 ---------
.../counterfactual/ActivateAccountFlow.tsx | 33 ++++++++------
.../counterfactual/CounterfactualForm.tsx | 4 +-
.../__tests__/useDeployGasLimit.test.ts | 1 -
.../counterfactual/hooks/useDeployGasLimit.ts | 3 +-
.../components/CancelRecoveryButton/index.tsx | 9 +---
.../ExecuteRecoveryButton/index.tsx | 12 ++---
.../speedup/components/SpeedUpModal.tsx | 25 ++++++++---
.../messages/useSyncSafeMessageSigner.ts | 9 +---
35 files changed, 186 insertions(+), 164 deletions(-)
delete mode 100644 src/components/tx/WrongChainWarning/index.tsx
diff --git a/src/components/common/ChainSwitcher/index.tsx b/src/components/common/ChainSwitcher/index.tsx
index 8c70c4f4ae..f0955d13c4 100644
--- a/src/components/common/ChainSwitcher/index.tsx
+++ b/src/components/common/ChainSwitcher/index.tsx
@@ -1,30 +1,57 @@
import type { ReactElement } from 'react'
-import { useCallback } from 'react'
-import { Box, Button } from '@mui/material'
+import { useCallback, useState } from 'react'
+import { Button, CircularProgress, Typography } from '@mui/material'
import { useCurrentChain } from '@/hooks/useChains'
import useOnboard from '@/hooks/wallets/useOnboard'
import useIsWrongChain from '@/hooks/useIsWrongChain'
-import css from './styles.module.css'
import { switchWalletChain } from '@/services/tx/tx-sender/sdk'
-const ChainSwitcher = ({ fullWidth }: { fullWidth?: boolean }): ReactElement | null => {
+const ChainSwitcher = ({
+ fullWidth,
+ primaryCta = false,
+}: {
+ fullWidth?: boolean
+ primaryCta?: boolean
+}): ReactElement | null => {
const chain = useCurrentChain()
const onboard = useOnboard()
const isWrongChain = useIsWrongChain()
+ const [loading, setIsLoading] = useState(false)
const handleChainSwitch = useCallback(async () => {
if (!onboard || !chain) return
-
+ setIsLoading(true)
await switchWalletChain(onboard, chain.chainId)
+ setIsLoading(false)
}, [chain, onboard])
if (!isWrongChain) return null
return (
-
- Switch to
-
- {chain?.chainName}
+
+ {loading ? (
+
+ ) : (
+ <>
+ Switch to
+
+ {chain?.chainName}
+ >
+ )}
)
}
diff --git a/src/components/common/CheckWallet/index.test.tsx b/src/components/common/CheckWallet/index.test.tsx
index 7172f1e920..35378993b9 100644
--- a/src/components/common/CheckWallet/index.test.tsx
+++ b/src/components/common/CheckWallet/index.test.tsx
@@ -2,6 +2,7 @@ import { render } from '@/tests/test-utils'
import CheckWallet from '.'
import useIsOnlySpendingLimitBeneficiary from '@/hooks/useIsOnlySpendingLimitBeneficiary'
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
+import useIsWrongChain from '@/hooks/useIsWrongChain'
import useWallet from '@/hooks/wallets/useWallet'
import { chainBuilder } from '@/tests/builders/chains'
@@ -31,7 +32,14 @@ jest.mock('@/hooks/useChains', () => ({
useCurrentChain: jest.fn(() => chainBuilder().build()),
}))
-const renderButton = () => render({(isOk) => Continue } )
+// mock useIsWrongChain
+jest.mock('@/hooks/useIsWrongChain', () => ({
+ __esModule: true,
+ default: jest.fn(() => false),
+}))
+
+const renderButton = () =>
+ render({(isOk) => Continue } )
describe('CheckWallet', () => {
beforeEach(() => {
@@ -69,6 +77,18 @@ describe('CheckWallet', () => {
)
})
+ it('should be disabled when connected to the wrong network', () => {
+ ;(useIsWrongChain as jest.MockedFunction).mockReturnValue(true)
+ ;(useIsSafeOwner as jest.MockedFunction).mockReturnValueOnce(true)
+
+ const renderButtonWithNetworkCheck = () =>
+ render({(isOk) => } )
+
+ const { container } = renderButtonWithNetworkCheck()
+
+ expect(container.querySelector('button')).toBeDisabled()
+ })
+
it('should not disable the button for non-owner spending limit benificiaries', () => {
;(useIsSafeOwner as jest.MockedFunction).mockReturnValueOnce(false)
;(
diff --git a/src/components/common/CheckWallet/index.tsx b/src/components/common/CheckWallet/index.tsx
index 59ab6e7c30..b354fb8f56 100644
--- a/src/components/common/CheckWallet/index.tsx
+++ b/src/components/common/CheckWallet/index.tsx
@@ -1,10 +1,11 @@
import { useIsWalletDelegate } from '@/hooks/useDelegates'
import { type ReactElement } from 'react'
-import { Tooltip } from '@mui/material'
import useIsOnlySpendingLimitBeneficiary from '@/hooks/useIsOnlySpendingLimitBeneficiary'
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
import useWallet from '@/hooks/wallets/useWallet'
import useConnectWallet from '../ConnectWallet/useConnectWallet'
+import useIsWrongChain from '@/hooks/useIsWrongChain'
+import { Tooltip } from '@mui/material'
import useSafeInfo from '@/hooks/useSafeInfo'
type CheckWalletProps = {
@@ -12,6 +13,7 @@ type CheckWalletProps = {
allowSpendingLimit?: boolean
allowNonOwner?: boolean
noTooltip?: boolean
+ checkNetwork?: boolean
}
enum Message {
@@ -20,14 +22,22 @@ enum Message {
CounterfactualMultisig = 'You need to activate the Safe before transacting',
}
-const CheckWallet = ({ children, allowSpendingLimit, allowNonOwner, noTooltip }: CheckWalletProps): ReactElement => {
+const CheckWallet = ({
+ children,
+ allowSpendingLimit,
+ allowNonOwner,
+ noTooltip,
+ checkNetwork = false,
+}: CheckWalletProps): ReactElement => {
const wallet = useWallet()
const isSafeOwner = useIsSafeOwner()
const isSpendingLimit = useIsOnlySpendingLimitBeneficiary()
const connectWallet = useConnectWallet()
+ const isWrongChain = useIsWrongChain()
const isDelegate = useIsWalletDelegate()
const { safe } = useSafeInfo()
+
const isCounterfactualMultiSig = !allowNonOwner && !safe.deployed && safe.threshold > 1
const message =
@@ -41,8 +51,8 @@ const CheckWallet = ({ children, allowSpendingLimit, allowNonOwner, noTooltip }:
? Message.CounterfactualMultisig
: Message.NotSafeOwner
+ if (checkNetwork && isWrongChain) return children(false)
if (!message) return children(true)
-
if (noTooltip) return children(false)
return (
diff --git a/src/components/new-safe/create/NetworkWarning/index.tsx b/src/components/new-safe/create/NetworkWarning/index.tsx
index 1a7aa01567..d0a87b5c72 100644
--- a/src/components/new-safe/create/NetworkWarning/index.tsx
+++ b/src/components/new-safe/create/NetworkWarning/index.tsx
@@ -1,17 +1,19 @@
import { Alert, AlertTitle, Box } from '@mui/material'
import { useCurrentChain } from '@/hooks/useChains'
import ChainSwitcher from '@/components/common/ChainSwitcher'
+import useIsWrongChain from '@/hooks/useIsWrongChain'
-const NetworkWarning = () => {
+const NetworkWarning = ({ action }: { action?: string }) => {
const chain = useCurrentChain()
+ const isWrongChain = useIsWrongChain()
- if (!chain) return null
+ if (!chain || !isWrongChain) return null
return (
-
+
Change your wallet network
- You are trying to create a Safe Account on {chain.chainName}. Make sure that your wallet is set to the same
- network.
+ You are trying to {action || 'sign or execute a transaction'} on {chain.chainName}. Make sure that your wallet is
+ set to the same network.
diff --git a/src/components/new-safe/create/steps/ReviewStep/index.test.tsx b/src/components/new-safe/create/steps/ReviewStep/index.test.tsx
index d369861243..23a7a67032 100644
--- a/src/components/new-safe/create/steps/ReviewStep/index.test.tsx
+++ b/src/components/new-safe/create/steps/ReviewStep/index.test.tsx
@@ -24,7 +24,7 @@ describe('NetworkFee', () => {
it('should display the total fee', () => {
jest.spyOn(useWallet, 'default').mockReturnValue({ label: 'MetaMask' } as unknown as ConnectedWallet)
const mockTotalFee = '0.0123'
- const result = render( )
+ const result = render( )
expect(result.getByText(`≈ ${mockTotalFee} ${mockChainInfo.nativeCurrency.symbol}`)).toBeInTheDocument()
})
diff --git a/src/components/new-safe/create/steps/ReviewStep/index.tsx b/src/components/new-safe/create/steps/ReviewStep/index.tsx
index 846813120d..dacaf084c3 100644
--- a/src/components/new-safe/create/steps/ReviewStep/index.tsx
+++ b/src/components/new-safe/create/steps/ReviewStep/index.tsx
@@ -43,17 +43,17 @@ import { ECOSYSTEM_ID_ADDRESS } from '@/config/constants'
export const NetworkFee = ({
totalFee,
chain,
- willRelay,
+ isWaived,
inline = false,
}: {
totalFee: string
chain: ChainInfo | undefined
- willRelay: boolean
+ isWaived: boolean
inline?: boolean
}) => {
return (
-
+
≈ {totalFee} {chain?.nativeCurrency.symbol}
@@ -288,7 +288,7 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps
You will have to confirm a transaction and pay an estimated fee of{' '}
- with your connected
+ with your connected
wallet
@@ -321,7 +321,7 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps
-
+
{!willRelay && (
@@ -333,7 +333,7 @@ const ReviewStep = ({ data, onSubmit, onBack, setStep }: StepRenderProps
- {isWrongChain && }
+
{!walletCanPay && !willRelay && (
diff --git a/src/components/new-safe/create/steps/ReviewStep/styles.module.css b/src/components/new-safe/create/steps/ReviewStep/styles.module.css
index 47bb71ae83..f495e3d665 100644
--- a/src/components/new-safe/create/steps/ReviewStep/styles.module.css
+++ b/src/components/new-safe/create/steps/ReviewStep/styles.module.css
@@ -5,7 +5,7 @@
font-size: 14px;
}
-.sponsoredFee {
+.strikethrough {
text-decoration: line-through;
color: var(--color-text-secondary);
}
diff --git a/src/components/new-safe/create/steps/SetNameStep/index.tsx b/src/components/new-safe/create/steps/SetNameStep/index.tsx
index a831ac4d2a..62c9b1b011 100644
--- a/src/components/new-safe/create/steps/SetNameStep/index.tsx
+++ b/src/components/new-safe/create/steps/SetNameStep/index.tsx
@@ -122,7 +122,10 @@ function SetNameStep({
.
- {isWrongChain && }
+
+
+
+
diff --git a/src/components/settings/PushNotifications/index.tsx b/src/components/settings/PushNotifications/index.tsx
index eeb1a11727..c3ae4f1c11 100644
--- a/src/components/settings/PushNotifications/index.tsx
+++ b/src/components/settings/PushNotifications/index.tsx
@@ -9,6 +9,8 @@ import {
Switch,
Divider,
Link as MuiLink,
+ useMediaQuery,
+ useTheme,
} from '@mui/material'
import Link from 'next/link'
import { useState } from 'react'
@@ -28,10 +30,10 @@ import { AppRoutes } from '@/config/routes'
import CheckWallet from '@/components/common/CheckWallet'
import { useIsMac } from '@/hooks/useIsMac'
import useOnboard from '@/hooks/wallets/useOnboard'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import ExternalLink from '@/components/common/ExternalLink'
import css from './styles.module.css'
+import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
export const PushNotifications = (): ReactElement => {
const { safe, safeLoaded } = useSafeInfo()
@@ -40,6 +42,8 @@ export const PushNotifications = (): ReactElement => {
const [isRegistering, setIsRegistering] = useState(false)
const [isUpdatingIndexedDb, setIsUpdatingIndexedDb] = useState(false)
const onboard = useOnboard()
+ const theme = useTheme()
+ const isLargeScreen = useMediaQuery(theme.breakpoints.up('lg'))
const { updatePreferences, getPreferences, getAllPreferences } = useNotificationPreferences()
const { unregisterSafeNotifications, unregisterDeviceNotifications, registerNotifications } =
@@ -58,18 +62,8 @@ export const PushNotifications = (): ReactElement => {
const shouldShowMacHelper = isMac || IS_DEV
const handleOnChange = async () => {
- if (!onboard) {
- return
- }
-
setIsRegistering(true)
- try {
- await assertWalletChain(onboard, safe.chainId)
- } catch {
- return
- }
-
if (!preferences) {
await registerNotifications({ [safe.chainId]: [safe.address.value] })
trackEvent(PUSH_NOTIFICATION_EVENTS.ENABLE_SAFE)
@@ -126,16 +120,17 @@ export const PushNotifications = (): ReactElement => {
{safeLoaded ? (
<>
+
-
+
{(isOk) => (
-
+
{(isOk) => (
diff --git a/src/components/transactions/SignTxButton/index.tsx b/src/components/transactions/SignTxButton/index.tsx
index 76298771c5..442cbe26a3 100644
--- a/src/components/transactions/SignTxButton/index.tsx
+++ b/src/components/transactions/SignTxButton/index.tsx
@@ -34,7 +34,7 @@ const SignTxButton = ({
}
return (
-
+
{(isOk) => (
diff --git a/src/components/tx-flow/common/TxLayout/index.tsx b/src/components/tx-flow/common/TxLayout/index.tsx
index de243b6d85..e3f1dc6b6b 100644
--- a/src/components/tx-flow/common/TxLayout/index.tsx
+++ b/src/components/tx-flow/common/TxLayout/index.tsx
@@ -83,7 +83,7 @@ const TxLayout = ({
const theme = useTheme()
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'))
- const isDesktop = useMediaQuery(theme.breakpoints.down('lg'))
+ const isDesktop = useMediaQuery(theme.breakpoints.down(1399.95))
const steps = Array.isArray(children) ? children : [children]
const progress = Math.round(((step + 1) / steps.length) * 100)
diff --git a/src/components/tx-flow/common/TxLayout/styles.module.css b/src/components/tx-flow/common/TxLayout/styles.module.css
index f8dfb36dfd..03b06e83ca 100644
--- a/src/components/tx-flow/common/TxLayout/styles.module.css
+++ b/src/components/tx-flow/common/TxLayout/styles.module.css
@@ -108,7 +108,7 @@
/* Height of transaction type title */
margin-top: 46px;
}
-@media (max-width: 1199.95px) {
+@media (max-width: 1399.95px) {
.backButton {
left: 50%;
transform: translateX(-50%);
diff --git a/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx b/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx
index cd30e55d6d..6739daad92 100644
--- a/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx
+++ b/src/components/tx-flow/flows/ExecuteBatch/ReviewBatch.tsx
@@ -1,5 +1,4 @@
import useWallet from '@/hooks/wallets/useWallet'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import { CircularProgress, Typography, Button, CardActions, Divider, Alert } from '@mui/material'
import useAsync from '@/hooks/useAsync'
import { FEATURES } from '@/utils/chains'
@@ -13,7 +12,6 @@ import ErrorMessage from '@/components/tx/ErrorMessage'
import { ExecutionMethod, ExecutionMethodSelector } from '@/components/tx/ExecutionMethodSelector'
import DecodedTxs from '@/components/tx-flow/flows/ExecuteBatch/DecodedTxs'
import { TxSimulation } from '@/components/tx/security/tenderly'
-import { WrongChainWarning } from '@/components/tx/WrongChainWarning'
import { useRelaysBySafe } from '@/hooks/useRemainingRelays'
import useOnboard from '@/hooks/wallets/useOnboard'
import { logError, Errors } from '@/services/exceptions'
@@ -40,6 +38,7 @@ import { getLatestSafeVersion } from '@/utils/chains'
import { HexEncodedData } from '@/components/transactions/HexEncodedData'
import { useGetMultipleTransactionDetailsQuery } from '@/store/gateway'
import { skipToken } from '@reduxjs/toolkit/query/react'
+import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
export const ReviewBatch = ({ params }: { params: ExecuteBatchFlowProps }) => {
const [isSubmittable, setIsSubmittable] = useState(true)
@@ -110,8 +109,6 @@ export const ReviewBatch = ({ params }: { params: ExecuteBatchFlowProps }) => {
overrides.nonce = userNonce
- await assertWalletChain(onboard, safe.chainId)
-
await dispatchBatchExecution(
txsWithDetails,
multiSendContract,
@@ -193,7 +190,7 @@ export const ReviewBatch = ({ params }: { params: ExecuteBatchFlowProps }) => {
-
+
{canRelay ? (
<>
@@ -227,7 +224,7 @@ export const ReviewBatch = ({ params }: { params: ExecuteBatchFlowProps }) => {
-
+
{(isOk) => (
Error submitting the transaction. Please try again.
)}
-
+
{recovery?.delay !== undefined && (
@@ -172,7 +169,7 @@ export function RecoverAccountFlowReview({ params }: { params: RecoverAccountFlo
-
+
{(isOk) => (
{
}))
jest.spyOn(useIsWrongChainHook, 'default').mockImplementation(() => false)
-
- jest.spyOn(sdk, 'assertWalletChain').mockImplementation(jest.fn())
})
describe('EIP-191 messages', () => {
@@ -367,14 +364,14 @@ describe('SignMessage', () => {
expect(getByText('Sign')).toBeDisabled()
})
- it('displays an error if connected to the wrong chain', () => {
+ it('displays a network switch warning if connected to the wrong chain', () => {
jest.spyOn(onboard, 'default').mockReturnValue(mockOnboard)
jest.spyOn(useIsSafeOwnerHook, 'default').mockImplementation(() => true)
jest.spyOn(useIsWrongChainHook, 'default').mockImplementation(() => true)
jest.spyOn(useChainsHook, 'useCurrentChain').mockReturnValue(chainBuilder().build())
jest.spyOn(useSafeMessage, 'default').mockImplementation(() => [undefined, jest.fn(), undefined])
- const { getByText } = render(
+ const { getByText, queryByText, container } = render(
{
/>,
)
- expect(getByText('Wallet network switch')).toBeInTheDocument()
-
- expect(getByText('Sign')).not.toBeDisabled()
+ expect(getByText('Change your wallet network')).toBeInTheDocument()
+ expect(queryByText('Sign')).toBeDisabled()
})
it('displays an error if not an owner', () => {
diff --git a/src/components/tx-flow/flows/SignMessage/SignMessage.tsx b/src/components/tx-flow/flows/SignMessage/SignMessage.tsx
index 7cfdce4b9f..603bb4918e 100644
--- a/src/components/tx-flow/flows/SignMessage/SignMessage.tsx
+++ b/src/components/tx-flow/flows/SignMessage/SignMessage.tsx
@@ -29,7 +29,6 @@ import useSafeMessage from '@/hooks/messages/useSafeMessage'
import useOnboard, { switchWallet } from '@/hooks/wallets/useOnboard'
import { TxModalContext } from '@/components/tx-flow'
import CopyButton from '@/components/common/CopyButton'
-import { WrongChainWarning } from '@/components/tx/WrongChainWarning'
import MsgSigners from '@/components/safe-messages/MsgSigners'
import useDecodedSafeMessage from '@/hooks/messages/useDecodedSafeMessage'
import useSyncSafeMessageSigner from '@/hooks/messages/useSyncSafeMessageSigner'
@@ -56,6 +55,8 @@ import { AppRoutes } from '@/config/routes'
import { useRouter } from 'next/router'
import MsgShareLink from '@/components/safe-messages/MsgShareLink'
import LinkIcon from '@/public/images/messages/link.svg'
+import CheckWallet from '@/components/common/CheckWallet'
+import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
const createSkeletonMessage = (confirmationsRequired: number): SafeMessage => {
return {
@@ -360,7 +361,7 @@ const SignMessage = ({ message, safeAppId, requestId }: ProposeProps | ConfirmPr
/>
)}
-
+
@@ -370,9 +371,13 @@ const SignMessage = ({ message, safeAppId, requestId }: ProposeProps | ConfirmPr
-
- Sign
-
+
+ {(isOk) => (
+
+ Sign
+
+ )}
+
>
diff --git a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx
index 5817b8ef76..1cc055aa17 100644
--- a/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx
+++ b/src/components/tx-flow/flows/SignMessageOnChain/ReviewSignMessageOnChain.tsx
@@ -1,5 +1,4 @@
import useWallet from '@/hooks/wallets/useWallet'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import type { ReactElement } from 'react'
import { useContext, useEffect, useState } from 'react'
import { useMemo } from 'react'
@@ -112,7 +111,6 @@ const ReviewSignMessageOnChain = ({ message, method, requestId }: SignMessageOnC
if (!safeTx || !onboard || !wallet) return
try {
- await assertWalletChain(onboard, safe.chainId)
await dispatchSafeAppsTx(safeTx, requestId, wallet.provider)
} catch (error) {
setSafeTxError(asError(error))
diff --git a/src/components/tx-flow/flows/TokenTransfer/ReviewSpendingLimitTx.tsx b/src/components/tx-flow/flows/TokenTransfer/ReviewSpendingLimitTx.tsx
index 277de59cc1..8c28146da8 100644
--- a/src/components/tx-flow/flows/TokenTransfer/ReviewSpendingLimitTx.tsx
+++ b/src/components/tx-flow/flows/TokenTransfer/ReviewSpendingLimitTx.tsx
@@ -1,5 +1,4 @@
import useWallet from '@/hooks/wallets/useWallet'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import type { ReactElement, SyntheticEvent } from 'react'
import { useContext, useMemo, useState } from 'react'
import { type BigNumberish, type BytesLike, parseUnits } from 'ethers'
@@ -21,7 +20,6 @@ import { dispatchSpendingLimitTxExecution } from '@/services/tx/tx-sender'
import { getTxOptions } from '@/utils/transactions'
import { MODALS_EVENTS, trackEvent } from '@/services/analytics'
import useOnboard from '@/hooks/wallets/useOnboard'
-import { WrongChainWarning } from '@/components/tx/WrongChainWarning'
import { asError } from '@/services/exceptions/utils'
import TxCard from '@/components/tx-flow/common/TxCard'
import { TxModalContext } from '@/components/tx-flow'
@@ -29,6 +27,8 @@ import { type SubmitCallback } from '@/components/tx/SignOrExecuteForm'
import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions'
import { isWalletRejection } from '@/utils/wallets'
import { safeParseUnits } from '@/utils/formatters'
+import CheckWallet from '@/components/common/CheckWallet'
+import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
export type SpendingLimitTxParams = {
safeAddress: string
@@ -103,7 +103,6 @@ const ReviewSpendingLimitTx = ({
const txOptions = getTxOptions(advancedParams, currentChain)
try {
- await assertWalletChain(onboard, safe.chainId)
await dispatchSpendingLimitTxExecution(txParams, txOptions, wallet.provider, safe.chainId, safeAddress)
onSubmit('', true)
setTxFlow(undefined)
@@ -140,7 +139,7 @@ const ReviewSpendingLimitTx = ({
-
+
{submitError && (
Error submitting the transaction. Please try again.
@@ -153,9 +152,13 @@ const ReviewSpendingLimitTx = ({
-
- Submit
-
+
+ {(isOk) => (
+
+ Submit
+
+ )}
+
diff --git a/src/components/tx/SignOrExecuteForm/DelegateForm.tsx b/src/components/tx/SignOrExecuteForm/DelegateForm.tsx
index c9f7777505..3e3f8f24d7 100644
--- a/src/components/tx/SignOrExecuteForm/DelegateForm.tsx
+++ b/src/components/tx/SignOrExecuteForm/DelegateForm.tsx
@@ -92,7 +92,7 @@ export const DelegateForm = ({
spacing={{ xs: 2, md: 2 }}
>
{/* Submit button */}
-
+
{(isOk) => (
{/* Submit button */}
-
+
{(isOk) => (
{/* Submit button, also available to non-owner role members */}
-
+
{(isOk) => (
+
{(isOk) => (
{
assertWallet(wallet)
assertOnboard(onboard)
- await assertWalletChain(onboard, chainId)
-
// Smart contract wallets must sign via an on-chain tx
if (await isSmartContractWallet(wallet.chainId, wallet.address)) {
// If the first signature is a smart contract wallet, we have to propose w/o signatures
@@ -105,8 +102,6 @@ export const useTxActions = (): TxActions => {
assertWallet(wallet)
assertOnboard(onboard)
- await assertWalletChain(onboard, chainId)
-
const signedTx = await dispatchDelegateTxSigning(safeTx, wallet)
const tx = await proposeTx(wallet.address, signedTx)
@@ -119,8 +114,6 @@ export const useTxActions = (): TxActions => {
assertOnboard(onboard)
assertChainInfo(chain)
- await assertWalletChain(onboard, chainId)
-
let tx: TransactionDetails | undefined
// Relayed transactions must be fully signed, so request a final signature if needed
if (isRelayed && safeTx.signatures.size < safe.threshold) {
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index 03bcc49df6..9b960e71cf 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -6,7 +6,6 @@ import { type ReactElement, type ReactNode, useState, useContext, useCallback }
import madProps from '@/utils/mad-props'
import DecodedTx from '../DecodedTx'
import ExecuteCheckbox from '../ExecuteCheckbox'
-import { WrongChainWarning } from '../WrongChainWarning'
import { useImmediatelyExecutable, useValidateNonce } from './hooks'
import ExecuteForm from './ExecuteForm'
import SignForm from './SignForm'
@@ -41,6 +40,7 @@ import { useApprovalInfos } from '../ApprovalEditor/hooks/useApprovalInfos'
import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { useGetTransactionDetailsQuery, useLazyGetTransactionDetailsQuery } from '@/store/gateway'
import { skipToken } from '@reduxjs/toolkit/query/react'
+import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
export type SubmitCallback = (txId: string, isExecuted?: boolean) => void
@@ -196,7 +196,7 @@ export const SignOrExecuteForm = ({
)}
-
+
diff --git a/src/components/tx/WrongChainWarning/index.tsx b/src/components/tx/WrongChainWarning/index.tsx
deleted file mode 100644
index 35cc18f9a1..0000000000
--- a/src/components/tx/WrongChainWarning/index.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import type { ReactElement } from 'react'
-import { Typography } from '@mui/material'
-import { useCurrentChain } from '@/hooks/useChains'
-import useIsWrongChain from '@/hooks/useIsWrongChain'
-import ErrorMessage from '@/components/tx/ErrorMessage'
-
-export const WrongChainWarning = (): ReactElement | null => {
- const chain = useCurrentChain()
- const isWrongChain = useIsWrongChain()
-
- if (!isWrongChain || !chain) {
- return null
- }
-
- return (
-
- Wallet network switch
- When you submit the transaction, you will be asked to switch your wallet network to {chain.chainName}.
-
- )
-}
diff --git a/src/features/counterfactual/ActivateAccountFlow.tsx b/src/features/counterfactual/ActivateAccountFlow.tsx
index a8a09dc56c..f58b8046ca 100644
--- a/src/features/counterfactual/ActivateAccountFlow.tsx
+++ b/src/features/counterfactual/ActivateAccountFlow.tsx
@@ -1,5 +1,4 @@
import { createNewSafe, relaySafeCreation } from '@/components/new-safe/create/logic'
-import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
import { NetworkFee, SafeSetupOverview } from '@/components/new-safe/create/steps/ReviewStep'
import ReviewRow from '@/components/new-safe/ReviewRow'
import { TxModalContext } from '@/components/tx-flow'
@@ -30,7 +29,9 @@ import { Box, Button, CircularProgress, Divider, Grid, Typography } from '@mui/m
import type { DeploySafeProps } from '@safe-global/protocol-kit'
import { FEATURES } from '@/utils/chains'
import React, { useContext, useState } from 'react'
+import CheckWallet from '@/components/common/CheckWallet'
import { getLatestSafeVersion } from '@/utils/chains'
+import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
const useActivateAccount = () => {
const chain = useCurrentChain()
@@ -162,11 +163,13 @@ const ActivateAccountFlow = () => {
name="Est. network fee"
value={
<>
-
+
{!willRelay && (
- You will have to confirm a transaction with your connected wallet.
+ {isWrongChain
+ ? `Switch your connected wallet to ${chain?.chainName} to see the correct estimated network fee`
+ : 'You will have to confirm a transaction with your connected wallet.'}
)}
>
@@ -180,7 +183,7 @@ const ActivateAccountFlow = () => {
)}
- {isWrongChain && }
+
{!walletCanPay && !willRelay && (
@@ -192,15 +195,19 @@ const ActivateAccountFlow = () => {
-
- {!isSubmittable ? : 'Activate'}
-
+
+ {(isOk) => (
+
+ {!isSubmittable ? : 'Activate'}
+
+ )}
+
diff --git a/src/features/counterfactual/CounterfactualForm.tsx b/src/features/counterfactual/CounterfactualForm.tsx
index cf20d005e5..de779ab68c 100644
--- a/src/features/counterfactual/CounterfactualForm.tsx
+++ b/src/features/counterfactual/CounterfactualForm.tsx
@@ -9,7 +9,6 @@ import useOnboard from '@/hooks/wallets/useOnboard'
import useWallet from '@/hooks/wallets/useWallet'
import { OVERVIEW_EVENTS, trackEvent, WALLET_EVENTS } from '@/services/analytics'
import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import madProps from '@/utils/mad-props'
import React, { type ReactElement, type SyntheticEvent, useContext, useState } from 'react'
import { CircularProgress, Box, Button, CardActions, Divider, Alert } from '@mui/material'
@@ -84,7 +83,6 @@ export const CounterfactualForm = ({
try {
trackEvent({ ...OVERVIEW_EVENTS.PROCEED_WITH_TX, label: TX_TYPES.activate_with_tx })
- onboard && (await assertWalletChain(onboard, chainId))
await deploySafeAndExecuteTx(txOptions, wallet, safeAddress, safeTx, wallet?.provider)
trackEvent({ ...TX_EVENTS.CREATE, label: TX_TYPES.activate_with_tx })
@@ -179,7 +177,7 @@ export const CounterfactualForm = ({
{/* Submit button */}
-
+
{(isOk) => (
{!isSubmittable ? : 'Execute'}
diff --git a/src/features/counterfactual/__tests__/useDeployGasLimit.test.ts b/src/features/counterfactual/__tests__/useDeployGasLimit.test.ts
index 4c1afcf5ba..c5ef2d8184 100644
--- a/src/features/counterfactual/__tests__/useDeployGasLimit.test.ts
+++ b/src/features/counterfactual/__tests__/useDeployGasLimit.test.ts
@@ -22,7 +22,6 @@ describe('useDeployGasLimit hook', () => {
jest.resetAllMocks()
jest.spyOn(useWallet, 'default').mockReturnValue({} as ConnectedWallet)
- jest.spyOn(sdk, 'assertWalletChain').mockImplementation(jest.fn())
})
it('returns undefined in onboard is not initialized', () => {
diff --git a/src/features/counterfactual/hooks/useDeployGasLimit.ts b/src/features/counterfactual/hooks/useDeployGasLimit.ts
index 777a270482..6731869354 100644
--- a/src/features/counterfactual/hooks/useDeployGasLimit.ts
+++ b/src/features/counterfactual/hooks/useDeployGasLimit.ts
@@ -2,7 +2,7 @@ import useAsync from '@/hooks/useAsync'
import useChainId from '@/hooks/useChainId'
import useOnboard from '@/hooks/wallets/useOnboard'
import useWallet from '@/hooks/wallets/useWallet'
-import { assertWalletChain, getSafeSDKWithSigner } from '@/services/tx/tx-sender/sdk'
+import { getSafeSDKWithSigner } from '@/services/tx/tx-sender/sdk'
import { estimateSafeDeploymentGas, estimateTxBaseGas } from '@safe-global/protocol-kit'
import type Safe from '@safe-global/protocol-kit'
@@ -28,7 +28,6 @@ const useDeployGasLimit = (safeTx?: SafeTransaction) => {
const [gasLimit, gasLimitError, gasLimitLoading] = useAsync(async () => {
if (!wallet || !onboard) return
- await assertWalletChain(onboard, chainId)
const sdk = await getSafeSDKWithSigner(wallet.provider)
const [baseGas, batchTxGas, safeDeploymentGas] = await Promise.all([
diff --git a/src/features/recovery/components/CancelRecoveryButton/index.tsx b/src/features/recovery/components/CancelRecoveryButton/index.tsx
index 0bb427872c..7247d79ceb 100644
--- a/src/features/recovery/components/CancelRecoveryButton/index.tsx
+++ b/src/features/recovery/components/CancelRecoveryButton/index.tsx
@@ -1,7 +1,6 @@
import useWallet from '@/hooks/wallets/useWallet'
import { trackEvent } from '@/services/analytics'
import { RECOVERY_EVENTS } from '@/services/analytics/events/recovery'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import { Button } from '@mui/material'
import { useContext } from 'react'
import type { SyntheticEvent, ReactElement } from 'react'
@@ -12,7 +11,6 @@ import { CancelRecoveryFlow } from '@/components/tx-flow/flows'
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
import { dispatchRecoverySkipExpired } from '@/features/recovery/services/recovery-sender'
import useSafeInfo from '@/hooks/useSafeInfo'
-import useOnboard from '@/hooks/wallets/useOnboard'
import { trackError, Errors } from '@/services/exceptions'
import { asError } from '@/services/exceptions/utils'
import { useRecoveryTxState } from '@/features/recovery/hooks/useRecoveryTxState'
@@ -30,7 +28,6 @@ export function CancelRecoveryButton({
const isOwner = useIsSafeOwner()
const { isExpired, isPending } = useRecoveryTxState(recovery)
const { setTxFlow } = useContext(TxModalContext)
- const onboard = useOnboard()
const wallet = useWallet()
const { safe } = useSafeInfo()
@@ -41,10 +38,8 @@ export function CancelRecoveryButton({
trackEvent(RECOVERY_EVENTS.CANCEL_RECOVERY)
if (isOwner) {
setTxFlow( )
- } else if (onboard && wallet) {
+ } else if (wallet) {
try {
- await assertWalletChain(onboard, safe.chainId)
-
await dispatchRecoverySkipExpired({
provider: wallet.provider,
chainId: safe.chainId,
@@ -62,7 +57,7 @@ export function CancelRecoveryButton({
}
return (
-
+
{(isOk) => {
const isDisabled = isPending || (isOwner ? !isOk : !isOk || !isExpired)
diff --git a/src/features/recovery/components/ExecuteRecoveryButton/index.tsx b/src/features/recovery/components/ExecuteRecoveryButton/index.tsx
index 5b3662d2f4..0112139dd7 100644
--- a/src/features/recovery/components/ExecuteRecoveryButton/index.tsx
+++ b/src/features/recovery/components/ExecuteRecoveryButton/index.tsx
@@ -1,5 +1,4 @@
import useWallet from '@/hooks/wallets/useWallet'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import { Button, Tooltip } from '@mui/material'
import { useContext } from 'react'
import type { SyntheticEvent, ReactElement } from 'react'
@@ -26,6 +25,7 @@ export function ExecuteRecoveryButton({
const onboard = useOnboard()
const wallet = useWallet()
const { safe } = useSafeInfo()
+ const isDisabled = !isExecutable || isPending
const onClick = async (e: SyntheticEvent) => {
e.stopPropagation()
@@ -36,8 +36,6 @@ export function ExecuteRecoveryButton({
}
try {
- await assertWalletChain(onboard, safe.chainId)
-
await dispatchRecoveryExecution({
provider: wallet.provider,
chainId: safe.chainId,
@@ -54,14 +52,12 @@ export function ExecuteRecoveryButton({
}
return (
-
+
{(isOk) => {
- const isDisabled = !isOk || !isExecutable || isPending
-
return (
diff --git a/src/features/speedup/components/SpeedUpModal.tsx b/src/features/speedup/components/SpeedUpModal.tsx
index 6f1a0eca19..f9606c3fad 100644
--- a/src/features/speedup/components/SpeedUpModal.tsx
+++ b/src/features/speedup/components/SpeedUpModal.tsx
@@ -1,8 +1,7 @@
import useGasPrice from '@/hooks/useGasPrice'
import ModalDialog from '@/components/common/ModalDialog'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import DialogContent from '@mui/material/DialogContent'
-import { Box, Button, SvgIcon, Tooltip, Typography } from '@mui/material'
+import { Box, Button, CircularProgress, SvgIcon, Tooltip, Typography } from '@mui/material'
import RocketSpeedup from '@/public/images/common/ic-rocket-speedup.svg'
import DialogActions from '@mui/material/DialogActions'
import useWallet from '@/hooks/wallets/useWallet'
@@ -27,7 +26,9 @@ import { TX_EVENTS } from '@/services/analytics/events/transactions'
import { getTransactionTrackingType } from '@/services/analytics/tx-tracking'
import { trackError } from '@/services/exceptions'
import ErrorCodes from '@/services/exceptions/ErrorCodes'
+import CheckWallet from '@/components/common/CheckWallet'
import { useLazyGetTransactionDetailsQuery } from '@/store/gateway'
+import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
type Props = {
open: boolean
@@ -91,7 +92,6 @@ export const SpeedUpModal = ({
try {
setWaitingForConfirmation(true)
- await assertWalletChain(onboard, chainInfo.chainId)
if (pendingTx.txType === PendingTxType.SAFE_TX) {
await dispatchSafeTxSpeedUp(
@@ -193,15 +193,28 @@ export const SpeedUpModal = ({
/>
)}
+
+
+
Cancel
-
- {isDisabled ? 'Waiting on confirmation in wallet...' : 'Confirm'}
-
+
+ {(isOk) => (
+
+ {isDisabled ? : 'Confirm'}
+
+ )}
+
diff --git a/src/hooks/messages/useSyncSafeMessageSigner.ts b/src/hooks/messages/useSyncSafeMessageSigner.ts
index a22a2014b9..cc6e4ca95f 100644
--- a/src/hooks/messages/useSyncSafeMessageSigner.ts
+++ b/src/hooks/messages/useSyncSafeMessageSigner.ts
@@ -3,7 +3,6 @@ import { Errors, logError } from '@/services/exceptions'
import { asError } from '@/services/exceptions/utils'
import { dispatchPreparedSignature } from '@/services/safe-messages/safeMsgNotifications'
import { dispatchSafeMsgProposal, dispatchSafeMsgConfirmation } from '@/services/safe-messages/safeMsgSender'
-import { assertWalletChain } from '@/services/tx/tx-sender/sdk'
import {
getSafeMessage,
SafeMessageListItemType,
@@ -12,7 +11,6 @@ import {
} from '@safe-global/safe-gateway-typescript-sdk'
import { useEffect, useCallback, useState } from 'react'
import useSafeInfo from '../useSafeInfo'
-import useOnboard from '../wallets/useOnboard'
const HIDE_DELAY = 3000
@@ -39,7 +37,6 @@ const useSyncSafeMessageSigner = (
onClose: () => void,
) => {
const [submitError, setSubmitError] = useState()
- const onboard = useOnboard()
const wallet = useWallet()
const { safe } = useSafeInfo()
@@ -54,15 +51,13 @@ const useSyncSafeMessageSigner = (
const onSign = useCallback(async () => {
// Error is shown when no wallet is connected, this appeases TypeScript
- if (!onboard || !wallet) {
+ if (!wallet) {
return
}
setSubmitError(undefined)
try {
- await assertWalletChain(onboard, safe.chainId)
-
// When collecting the first signature
if (!message) {
await dispatchSafeMsgProposal({ provider: wallet.provider, safe, message: decodedMessage, safeAppId })
@@ -91,7 +86,7 @@ const useSyncSafeMessageSigner = (
} catch (e) {
setSubmitError(asError(e))
}
- }, [onboard, wallet, safe, message, decodedMessage, safeAppId, safeMessageHash, onClose, requestId])
+ }, [wallet, safe, message, decodedMessage, safeAppId, safeMessageHash, onClose, requestId])
return { submitError, onSign }
}
From 19dc7b95a236c5c3b8c6fcfd347522fd0bcc4f1e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=B3vis=20Neto?=
Date: Tue, 10 Sep 2024 20:35:57 +0200
Subject: [PATCH 56/81] fix: avoid cleaning the async data when there is a
reconsilation in the component (#4149)
---
src/components/tx/SignOrExecuteForm/index.tsx | 3 ++-
src/hooks/useDecodeTx.ts | 18 +++++++++++-------
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index 9b960e71cf..55f4ea1456 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -94,6 +94,7 @@ export const SignOrExecuteForm = ({
const isNewExecutableTx = useImmediatelyExecutable() && isCreation
const isCorrectNonce = useValidateNonce(safeTx)
const [decodedData] = useDecodeTx(safeTx)
+
const isBatchable = props.isBatchable !== false && safeTx && !isDelegateCall(safeTx)
const isSwapOrder = isConfirmationViewOrder(decodedData)
const { data: txDetails } = useGetTransactionDetailsQuery(
@@ -159,7 +160,7 @@ export const SignOrExecuteForm = ({
)}
- {!props.isRejection && (
+ {!props.isRejection && decodedData && (
Error parsing data }>
{isApproval && }
diff --git a/src/hooks/useDecodeTx.ts b/src/hooks/useDecodeTx.ts
index f4fbfd0127..72d9b57040 100644
--- a/src/hooks/useDecodeTx.ts
+++ b/src/hooks/useDecodeTx.ts
@@ -23,13 +23,17 @@ const useDecodeTx = (
const [data, error, loading] = useAsync<
DecodedDataResponse | BaselineConfirmationView | OrderConfirmationView | undefined
- >(() => {
- if (!encodedData || isEmptyData) {
- const nativeTransfer = isEmptyData && !isRejection ? getNativeTransferData(tx?.data) : undefined
- return Promise.resolve(nativeTransfer)
- }
- return getConfirmationView(chainId, safeAddress, encodedData, tx.data.to)
- }, [chainId, encodedData, isEmptyData, tx?.data, isRejection, safeAddress])
+ >(
+ () => {
+ if (!encodedData || isEmptyData) {
+ const nativeTransfer = isEmptyData && !isRejection ? getNativeTransferData(tx?.data) : undefined
+ return Promise.resolve(nativeTransfer)
+ }
+ return getConfirmationView(chainId, safeAddress, encodedData, tx.data.to)
+ },
+ [chainId, encodedData, isEmptyData, tx?.data, isRejection, safeAddress],
+ false,
+ )
return [data, error, loading]
}
From 2182761fab13891e2b6d11a708a8c7416f4afded Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Wed, 11 Sep 2024 10:53:50 +0200
Subject: [PATCH 57/81] Chore: update walletconnect packages (#4152)
---
package.json | 6 +--
yarn.lock | 123 ++++++++++++++++++++++++++++++++-------------------
2 files changed, 80 insertions(+), 49 deletions(-)
diff --git a/package.json b/package.json
index c7d20ee6bd..32040e257d 100644
--- a/package.json
+++ b/package.json
@@ -62,8 +62,8 @@
"@safe-global/safe-modules-deployments": "^1.2.0",
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
- "@walletconnect/utils": "^2.15.2",
- "@walletconnect/web3wallet": "^1.15.0",
+ "@walletconnect/utils": "^2.16.1",
+ "@walletconnect/web3wallet": "^1.15.1",
"@web3-onboard/coinbase": "^2.2.6",
"@web3-onboard/core": "^2.21.4",
"@web3-onboard/injected-wallets": "^2.11.2",
@@ -128,7 +128,7 @@
"@types/react-gtm-module": "^2.0.3",
"@types/semver": "^7.3.10",
"@typescript-eslint/eslint-plugin": "^7.6.0",
- "@walletconnect/types": "^2.15.2",
+ "@walletconnect/types": "^2.16.1",
"cross-env": "^7.0.3",
"cypress": "^12.15.0",
"cypress-file-upload": "^5.0.8",
diff --git a/yarn.lock b/yarn.lock
index 7d8b6899ad..86b0fa4c1e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -6449,7 +6449,29 @@
lodash.isequal "4.5.0"
uint8arrays "^3.1.0"
-"@walletconnect/core@2.16.0", "@walletconnect/core@^2.10.1":
+"@walletconnect/core@2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.16.1.tgz#019b181387792e0d284e75074b961b48193d9b6a"
+ integrity sha512-UlsnEMT5wwFvmxEjX8s4oju7R3zadxNbZgsFeHEsjh7uknY2zgmUe1Lfc5XU6zyPb1Jx7Nqpdx1KN485ee8ogw==
+ dependencies:
+ "@walletconnect/heartbeat" "1.2.2"
+ "@walletconnect/jsonrpc-provider" "1.0.14"
+ "@walletconnect/jsonrpc-types" "1.0.4"
+ "@walletconnect/jsonrpc-utils" "1.0.8"
+ "@walletconnect/jsonrpc-ws-connection" "1.0.14"
+ "@walletconnect/keyvaluestorage" "1.1.1"
+ "@walletconnect/logger" "2.1.2"
+ "@walletconnect/relay-api" "1.0.11"
+ "@walletconnect/relay-auth" "1.0.4"
+ "@walletconnect/safe-json" "1.0.2"
+ "@walletconnect/time" "1.0.2"
+ "@walletconnect/types" "2.16.1"
+ "@walletconnect/utils" "2.16.1"
+ events "3.3.0"
+ lodash.isequal "4.5.0"
+ uint8arrays "3.1.0"
+
+"@walletconnect/core@^2.10.1":
version "2.16.0"
resolved "https://registry.yarnpkg.com/@walletconnect/core/-/core-2.16.0.tgz#751eb0b9bcd24a0035c87a1be63c830b86dad3de"
integrity sha512-B/PPcg0MRb9pqB6nupVqEFGI5cFK5HNXYoi+y6Qaq53JIjHa6KANskNkj567iegETaPUZIniHENry7M8mHN3Bw==
@@ -6674,19 +6696,19 @@
"@walletconnect/utils" "2.11.2"
events "^3.3.0"
-"@walletconnect/sign-client@2.16.0":
- version "2.16.0"
- resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.16.0.tgz#80abe30b86431e6c2e3287a98df973203fec1559"
- integrity sha512-R9C9D8jaARbosXvA9IGIAowashGqp9avmjx6gikH4lKq2qhDjD5CWZq+GrN6gcht6WQiQ1mNmrmhN1pBPvivwQ==
+"@walletconnect/sign-client@2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/sign-client/-/sign-client-2.16.1.tgz#94a2f630ba741bd180f540c53576c5ceaace4857"
+ integrity sha512-s2Tx2n2duxt+sHtuWXrN9yZVaHaYqcEcjwlTD+55/vs5NUPlISf+fFmZLwSeX1kUlrSBrAuxPUcqQuRTKcjLOA==
dependencies:
- "@walletconnect/core" "2.16.0"
+ "@walletconnect/core" "2.16.1"
"@walletconnect/events" "1.0.1"
"@walletconnect/heartbeat" "1.2.2"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "2.1.2"
"@walletconnect/time" "1.0.2"
- "@walletconnect/types" "2.16.0"
- "@walletconnect/utils" "2.16.0"
+ "@walletconnect/types" "2.16.1"
+ "@walletconnect/utils" "2.16.1"
events "3.3.0"
"@walletconnect/time@1.0.2", "@walletconnect/time@^1.0.2":
@@ -6708,7 +6730,7 @@
"@walletconnect/logger" "^2.0.1"
events "^3.3.0"
-"@walletconnect/types@2.16.0", "@walletconnect/types@^2.15.2":
+"@walletconnect/types@2.16.0":
version "2.16.0"
resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.16.0.tgz#1719bbde7bd6316e8167ab47e6cbb441c4f168dc"
integrity sha512-n+vpli0eonAzG9wtOgmjYbJEMGz2gvOttU2VnzNkeVmvDz7otVuPgtk+7BNyRofZ6rBW6rriW5cCKtmbzvUSzA==
@@ -6720,6 +6742,18 @@
"@walletconnect/logger" "2.1.2"
events "3.3.0"
+"@walletconnect/types@2.16.1", "@walletconnect/types@^2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/types/-/types-2.16.1.tgz#6583d458d3f7b1919d482ba516ccb7878ec8c91f"
+ integrity sha512-9P4RG4VoDEF+yBF/n2TF12gsvT/aTaeZTVDb/AOayafqiPnmrQZMKmNCJJjq1sfdsDcHXFcZWMGsuCeSJCmrXA==
+ dependencies:
+ "@walletconnect/events" "1.0.1"
+ "@walletconnect/heartbeat" "1.2.2"
+ "@walletconnect/jsonrpc-types" "1.0.4"
+ "@walletconnect/keyvaluestorage" "1.1.1"
+ "@walletconnect/logger" "2.1.2"
+ events "3.3.0"
+
"@walletconnect/universal-provider@2.11.2":
version "2.11.2"
resolved "https://registry.yarnpkg.com/@walletconnect/universal-provider/-/universal-provider-2.11.2.tgz#bec3038f51445d707bbec75f0cb8af0a1f1e04db"
@@ -6755,7 +6789,7 @@
query-string "7.1.3"
uint8arrays "^3.1.0"
-"@walletconnect/utils@2.16.0", "@walletconnect/utils@^2.10.1", "@walletconnect/utils@^2.15.2":
+"@walletconnect/utils@2.16.0", "@walletconnect/utils@^2.10.1":
version "2.16.0"
resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.16.0.tgz#0696655035dce9efcc209e5c789b7e22b085a70d"
integrity sha512-ASh9yyqzP4GLIU400rKEvBefcM5GFJbi2Iw7p0SFDyFC5WZYYyllU3WopU+YV/7bbukCMkthEIdioWYlpmjERQ==
@@ -6777,19 +6811,41 @@
query-string "7.1.3"
uint8arrays "3.1.0"
-"@walletconnect/web3wallet@^1.15.0":
- version "1.15.0"
- resolved "https://registry.yarnpkg.com/@walletconnect/web3wallet/-/web3wallet-1.15.0.tgz#745fab0d0fc22e0ce1c5f9880c865dde3aaa3e8e"
- integrity sha512-tJbH/I8MJrKSEiLGlj0wmB4J1bB0dBoY1hRFMX3CCCkCB+ZFvJeoeC5LjTJRtSOqCk10ABp9uvII/18tYyxXnA==
+"@walletconnect/utils@2.16.1", "@walletconnect/utils@^2.16.1":
+ version "2.16.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/utils/-/utils-2.16.1.tgz#2099cc2bd16b0edc32022f64aa2c2c323b45d1d4"
+ integrity sha512-aoQirVoDoiiEtYeYDtNtQxFzwO/oCrz9zqeEEXYJaAwXlGVTS34KFe7W3/Rxd/pldTYKFOZsku2EzpISfH8Wsw==
+ 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.11"
+ "@walletconnect/relay-auth" "1.0.4"
+ "@walletconnect/safe-json" "1.0.2"
+ "@walletconnect/time" "1.0.2"
+ "@walletconnect/types" "2.16.1"
+ "@walletconnect/window-getters" "1.0.1"
+ "@walletconnect/window-metadata" "1.0.1"
+ detect-browser "5.3.0"
+ elliptic "^6.5.7"
+ query-string "7.1.3"
+ uint8arrays "3.1.0"
+
+"@walletconnect/web3wallet@^1.15.1":
+ version "1.15.1"
+ resolved "https://registry.yarnpkg.com/@walletconnect/web3wallet/-/web3wallet-1.15.1.tgz#47d041c07e2b12824ade85e53ed50c89536ef37b"
+ integrity sha512-EgtdZUgtf0diU98x8Q8tiZslE0Z5comnxv3SqmAIgkdhpXDxaM/goo7BC1yC+Wey/IHOOVYg2SW+La2Txk+6hQ==
dependencies:
"@walletconnect/auth-client" "2.1.2"
- "@walletconnect/core" "2.16.0"
+ "@walletconnect/core" "2.16.1"
"@walletconnect/jsonrpc-provider" "1.0.14"
"@walletconnect/jsonrpc-utils" "1.0.8"
"@walletconnect/logger" "2.1.2"
- "@walletconnect/sign-client" "2.16.0"
- "@walletconnect/types" "2.16.0"
- "@walletconnect/utils" "2.16.0"
+ "@walletconnect/sign-client" "2.16.1"
+ "@walletconnect/types" "2.16.1"
+ "@walletconnect/utils" "2.16.1"
"@walletconnect/window-getters@1.0.1", "@walletconnect/window-getters@^1.0.1":
version "1.0.1"
@@ -16623,16 +16679,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16720,14 +16767,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", 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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18412,7 +18452,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18430,15 +18470,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From 03f72cd2ce2edec560b4c6a902e522c635e702e7 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 11 Sep 2024 12:48:09 +0200
Subject: [PATCH 58/81] Chore(deps): Bump the npm_and_yarn group with 4 updates
(#4153)
Bumps the npm_and_yarn group with 4 updates: [webpack](https://github.com/webpack/webpack), [express](https://github.com/expressjs/express), [path-to-regexp](https://github.com/pillarjs/path-to-regexp) and [serve-static](https://github.com/expressjs/serve-static).
Updates `webpack` from 5.91.0 to 5.94.0
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.91.0...v5.94.0)
Updates `express` from 4.19.2 to 4.20.0
- [Release notes](https://github.com/expressjs/express/releases)
- [Changelog](https://github.com/expressjs/express/blob/master/History.md)
- [Commits](https://github.com/expressjs/express/compare/4.19.2...4.20.0)
Updates `path-to-regexp` from 0.1.7 to 0.1.10
- [Release notes](https://github.com/pillarjs/path-to-regexp/releases)
- [Changelog](https://github.com/pillarjs/path-to-regexp/blob/master/History.md)
- [Commits](https://github.com/pillarjs/path-to-regexp/compare/v0.1.7...v0.1.10)
Updates `serve-static` from 1.15.0 to 1.16.0
- [Release notes](https://github.com/expressjs/serve-static/releases)
- [Changelog](https://github.com/expressjs/serve-static/blob/master/HISTORY.md)
- [Commits](https://github.com/expressjs/serve-static/compare/v1.15.0...1.16.0)
---
updated-dependencies:
- dependency-name: webpack
dependency-type: direct:development
dependency-group: npm_and_yarn
- dependency-name: express
dependency-type: indirect
dependency-group: npm_and_yarn
- dependency-name: path-to-regexp
dependency-type: indirect
dependency-group: npm_and_yarn
- dependency-name: serve-static
dependency-type: indirect
dependency-group: npm_and_yarn
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 171 +++++++++++++++++++++++++++++++--------------------
2 files changed, 106 insertions(+), 67 deletions(-)
diff --git a/package.json b/package.json
index 32040e257d..f2adfc11cb 100644
--- a/package.json
+++ b/package.json
@@ -151,7 +151,7 @@
"typechain": "^8.3.2",
"typescript": "^5.4.5",
"typescript-plugin-css-modules": "^4.2.2",
- "webpack": "^5.88.2"
+ "webpack": "^5.94.0"
},
"nextBundleAnalysis": {
"budget": null,
diff --git a/yarn.lock b/yarn.lock
index 86b0fa4c1e..29c9a0c59f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5754,27 +5754,6 @@
resolved "https://registry.yarnpkg.com/@types/escodegen/-/escodegen-0.0.6.tgz#5230a9ce796e042cda6f086dbf19f22ea330659c"
integrity sha512-AjwI4MvWx3HAOaZqYsjKWyEObT9lcVV0Y0V8nXo6cXzN8ZiMxVhf6F3d/UNvXVGKrEzL/Dluc5p+y9GkzlTWig==
-"@types/eslint-scope@^3.7.3":
- version "3.7.5"
- resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.5.tgz#e28b09dbb1d9d35fdfa8a884225f00440dfc5a3e"
- integrity sha512-JNvhIEyxVW6EoMIFIvj93ZOywYFatlpu9deeH6eSx6PE3WHYvHaQtmHmQeNw7aA81bYGBPPQqdtBm6b1SsQMmA==
- dependencies:
- "@types/eslint" "*"
- "@types/estree" "*"
-
-"@types/eslint@*":
- version "8.44.4"
- resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.44.4.tgz#28eaff82e1ca0a96554ec5bb0188f10ae1a74c2f"
- integrity sha512-lOzjyfY/D9QR4hY9oblZ76B90MYTB3RrQ4z2vBIJKj9ROCRqdkYl2gSUx1x1a4IWPjKJZLL4Aw1Zfay7eMnmnA==
- dependencies:
- "@types/estree" "*"
- "@types/json-schema" "*"
-
-"@types/estree@*", "@types/estree@^1.0.0", "@types/estree@^1.0.5":
- version "1.0.5"
- resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
- integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
-
"@types/estree@0.0.39":
version "0.0.39"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.39.tgz#e177e699ee1b8c22d23174caaa7422644389509f"
@@ -5785,6 +5764,11 @@
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40"
integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==
+"@types/estree@^1.0.0", "@types/estree@^1.0.5":
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
+ integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
+
"@types/express-serve-static-core@^4.17.33":
version "4.19.0"
resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.19.0.tgz#3ae8ab3767d98d0b682cda063c3339e1e86ccfaa"
@@ -5878,7 +5862,7 @@
"@types/tough-cookie" "*"
parse5 "^7.0.0"
-"@types/json-schema@*", "@types/json-schema@^7.0.15", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
+"@types/json-schema@^7.0.15", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
version "7.0.15"
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"
integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==
@@ -7169,10 +7153,10 @@ acorn-globals@^7.0.0:
acorn "^8.1.0"
acorn-walk "^8.0.2"
-acorn-import-assertions@^1.9.0:
- version "1.9.0"
- resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
- integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==
+acorn-import-attributes@^1.9.5:
+ version "1.9.5"
+ resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef"
+ integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==
acorn-jsx@^5.3.1, acorn-jsx@^5.3.2:
version "5.3.2"
@@ -7965,10 +7949,10 @@ bnc-sdk@^4.6.7:
rxjs "^6.6.3"
sturdy-websocket "^0.1.12"
-body-parser@1.20.2:
- version "1.20.2"
- resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
- integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
+body-parser@1.20.3:
+ version "1.20.3"
+ resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
+ integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
dependencies:
bytes "3.1.2"
content-type "~1.0.5"
@@ -7978,7 +7962,7 @@ body-parser@1.20.2:
http-errors "2.0.0"
iconv-lite "0.4.24"
on-finished "2.4.1"
- qs "6.11.0"
+ qs "6.13.0"
raw-body "2.5.2"
type-is "~1.6.18"
unpipe "1.0.0"
@@ -9653,6 +9637,11 @@ encodeurl@~1.0.2:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
+encodeurl@~2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
+ integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
+
end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@@ -9669,10 +9658,10 @@ endent@^2.0.1:
fast-json-parse "^1.0.3"
objectorarray "^1.0.5"
-enhanced-resolve@^5.12.0, enhanced-resolve@^5.16.0, enhanced-resolve@^5.7.0:
- version "5.16.0"
- resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz#65ec88778083056cb32487faa9aef82ed0864787"
- integrity sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==
+enhanced-resolve@^5.12.0, enhanced-resolve@^5.17.1, enhanced-resolve@^5.7.0:
+ version "5.17.1"
+ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15"
+ integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==
dependencies:
graceful-fs "^4.2.4"
tapable "^2.2.0"
@@ -10668,36 +10657,36 @@ exponential-backoff@^3.1.0:
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
express@^4.17.3:
- version "4.19.2"
- resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
- integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
+ version "4.20.0"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.20.0.tgz#f1d08e591fcec770c07be4767af8eb9bcfd67c48"
+ integrity sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==
dependencies:
accepts "~1.3.8"
array-flatten "1.1.1"
- body-parser "1.20.2"
+ body-parser "1.20.3"
content-disposition "0.5.4"
content-type "~1.0.4"
cookie "0.6.0"
cookie-signature "1.0.6"
debug "2.6.9"
depd "2.0.0"
- encodeurl "~1.0.2"
+ encodeurl "~2.0.0"
escape-html "~1.0.3"
etag "~1.8.1"
finalhandler "1.2.0"
fresh "0.5.2"
http-errors "2.0.0"
- merge-descriptors "1.0.1"
+ merge-descriptors "1.0.3"
methods "~1.1.2"
on-finished "2.4.1"
parseurl "~1.3.3"
- path-to-regexp "0.1.7"
+ path-to-regexp "0.1.10"
proxy-addr "~2.0.7"
qs "6.11.0"
range-parser "~1.2.1"
safe-buffer "5.2.1"
- send "0.18.0"
- serve-static "1.15.0"
+ send "0.19.0"
+ serve-static "1.16.0"
setprototypeof "1.2.0"
statuses "2.0.1"
type-is "~1.6.18"
@@ -13696,10 +13685,10 @@ meow@^9.0.0:
type-fest "^0.18.0"
yargs-parser "^20.2.3"
-merge-descriptors@1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
- integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
+merge-descriptors@1.0.3:
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
+ integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
merge-options@^3.0.4:
version "3.0.4"
@@ -14627,10 +14616,10 @@ path-scurry@^1.10.1, path-scurry@^1.10.2:
lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.0"
-path-to-regexp@0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
- integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
+path-to-regexp@0.1.10:
+ version "0.1.10"
+ resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b"
+ integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==
path-type@^4.0.0:
version "4.0.0"
@@ -15199,6 +15188,13 @@ qs@6.11.0:
dependencies:
side-channel "^1.0.4"
+qs@6.13.0:
+ version "6.13.0"
+ resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
+ integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
+ dependencies:
+ side-channel "^1.0.6"
+
qs@^6.10.0, qs@^6.10.3, qs@^6.11.2:
version "6.12.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.12.0.tgz#edd40c3b823995946a8a0b1f208669c7a200db77"
@@ -16245,6 +16241,25 @@ send@0.18.0:
range-parser "~1.2.1"
statuses "2.0.1"
+send@0.19.0:
+ version "0.19.0"
+ resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
+ integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
+ dependencies:
+ debug "2.6.9"
+ depd "2.0.0"
+ destroy "1.2.0"
+ encodeurl "~1.0.2"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ mime "1.6.0"
+ ms "2.1.3"
+ on-finished "2.4.1"
+ range-parser "~1.2.1"
+ statuses "2.0.1"
+
serialize-javascript@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-4.0.0.tgz#b525e1238489a5ecfc42afacc3fe99e666f4b1aa"
@@ -16259,10 +16274,10 @@ serialize-javascript@^6.0.1:
dependencies:
randombytes "^2.1.0"
-serve-static@1.15.0:
- version "1.15.0"
- resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
- integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
+serve-static@1.16.0:
+ version "1.16.0"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92"
+ integrity sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==
dependencies:
encodeurl "~1.0.2"
escape-html "~1.0.3"
@@ -16679,7 +16694,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16767,7 +16791,14 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18103,21 +18134,20 @@ webpack-virtual-modules@^0.6.1:
resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.1.tgz#ac6fdb9c5adb8caecd82ec241c9631b7a3681b6f"
integrity sha512-poXpCylU7ExuvZK8z+On3kX+S8o/2dQ/SVYueKA0D4WEMXROXgY8Ez50/bQEUmvoSMMrWcrJqCHuhAbsiwg7Dg==
-webpack@5, webpack@^5.88.2:
- version "5.91.0"
- resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.91.0.tgz#ffa92c1c618d18c878f06892bbdc3373c71a01d9"
- integrity sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==
+webpack@5, webpack@^5.94.0:
+ version "5.94.0"
+ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f"
+ integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==
dependencies:
- "@types/eslint-scope" "^3.7.3"
"@types/estree" "^1.0.5"
"@webassemblyjs/ast" "^1.12.1"
"@webassemblyjs/wasm-edit" "^1.12.1"
"@webassemblyjs/wasm-parser" "^1.12.1"
acorn "^8.7.1"
- acorn-import-assertions "^1.9.0"
+ acorn-import-attributes "^1.9.5"
browserslist "^4.21.10"
chrome-trace-event "^1.0.2"
- enhanced-resolve "^5.16.0"
+ enhanced-resolve "^5.17.1"
es-module-lexer "^1.2.1"
eslint-scope "5.1.1"
events "^3.2.0"
@@ -18452,7 +18482,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18470,6 +18500,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From 5e798c9a1e16e12bd4d39abb5773ce852087da71 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Wed, 11 Sep 2024 16:21:56 +0200
Subject: [PATCH 59/81] Feat: add native staking teaser in sidebar (#4154)
* Feat: add native staking teaser in sidebar
* Styles
* Feature toggle and tooltip
---
public/images/common/stake.svg | 4 ++
src/components/common/Chip/index.tsx | 39 ++++++++++++++++---
src/components/sidebar/SidebarList/index.tsx | 3 +-
.../sidebar/SidebarNavigation/config.tsx | 12 +++++-
.../sidebar/SidebarNavigation/index.tsx | 33 ++++++++--------
src/config/routes.ts | 1 +
src/utils/chains.ts | 2 +
7 files changed, 69 insertions(+), 25 deletions(-)
create mode 100644 public/images/common/stake.svg
diff --git a/public/images/common/stake.svg b/public/images/common/stake.svg
new file mode 100644
index 0000000000..b0a4b399df
--- /dev/null
+++ b/public/images/common/stake.svg
@@ -0,0 +1,4 @@
+
+
+
+
diff --git a/src/components/common/Chip/index.tsx b/src/components/common/Chip/index.tsx
index 81bb623685..5cf901d4be 100644
--- a/src/components/common/Chip/index.tsx
+++ b/src/components/common/Chip/index.tsx
@@ -1,8 +1,35 @@
-import { Chip as MuiChip } from '@mui/material'
-import type { ChipProps } from '@mui/material'
-import type { ReactElement } from 'react'
-import React from 'react'
+import { Typography, Chip as MuiChip } from '@mui/material'
-export function Chip(props: ChipProps): ReactElement {
- return
+type ChipProps = {
+ label?: string
+ color?: 'primary' | 'secondary' | 'info' | 'warning' | 'success' | 'error'
+}
+
+export function Chip({ color = 'primary', label = 'New' }: ChipProps) {
+ return (
+
+ {label}
+
+ }
+ />
+ )
}
diff --git a/src/components/sidebar/SidebarList/index.tsx b/src/components/sidebar/SidebarList/index.tsx
index 409275b249..ae5e59742f 100644
--- a/src/components/sidebar/SidebarList/index.tsx
+++ b/src/components/sidebar/SidebarList/index.tsx
@@ -18,10 +18,11 @@ export const SidebarList = ({ children, ...rest }: Omit)
export const SidebarListItemButton = ({
href,
children,
+ disabled,
...rest
}: Omit & { href?: LinkProps['href'] }): ReactElement => {
const button = (
-
+
{children}
)
diff --git a/src/components/sidebar/SidebarNavigation/config.tsx b/src/components/sidebar/SidebarNavigation/config.tsx
index ea7778a259..94e6d470dc 100644
--- a/src/components/sidebar/SidebarNavigation/config.tsx
+++ b/src/components/sidebar/SidebarNavigation/config.tsx
@@ -8,6 +8,7 @@ import ABIcon from '@/public/images/sidebar/address-book.svg'
import AppsIcon from '@/public/images/apps/apps-icon.svg'
import SettingsIcon from '@/public/images/sidebar/settings.svg'
import SwapIcon from '@/public/images/common/swap.svg'
+import StakeIcon from '@/public/images/common/stake.svg'
import { SvgIcon } from '@mui/material'
import { Chip } from '@/components/common/Chip'
@@ -16,6 +17,8 @@ export type NavItem = {
icon?: ReactElement
href: string
tag?: ReactElement
+ disabled?: boolean
+ tooltip?: string
}
export const navItems: NavItem[] = [
@@ -33,7 +36,14 @@ export const navItems: NavItem[] = [
label: 'Swap',
icon: ,
href: AppRoutes.swap,
- tag: ,
+ },
+ {
+ label: 'Stake',
+ icon: ,
+ href: AppRoutes.stake,
+ tag: ,
+ disabled: true,
+ tooltip: 'Native staking is coming soon, stay tuned!',
},
{
label: 'Transactions',
diff --git a/src/components/sidebar/SidebarNavigation/index.tsx b/src/components/sidebar/SidebarNavigation/index.tsx
index 1a5632c803..d7b38f8544 100644
--- a/src/components/sidebar/SidebarNavigation/index.tsx
+++ b/src/components/sidebar/SidebarNavigation/index.tsx
@@ -19,6 +19,7 @@ import { isRouteEnabled } from '@/utils/chains'
import { trackEvent } from '@/services/analytics'
import { SWAP_EVENTS, SWAP_LABELS } from '@/services/analytics/events/swaps'
import { GeoblockingContext } from '@/components/common/GeoblockingProvider'
+import { Tooltip } from '@mui/material'
const getSubdirectory = (pathname: string): string => {
return pathname.split('/')[1]
@@ -75,25 +76,23 @@ const Navigation = (): ReactElement => {
}
return (
- handleNavigationClick(item.href)}
- >
-
- {item.icon && {item.icon} }
+
+ handleNavigationClick(item.href)}>
+
+ {item.icon && {item.icon} }
-
- {item.label}
+
+ {item.label}
- {ItemTag}
-
-
-
+ {ItemTag}
+
+
+
+
)
})}
diff --git a/src/config/routes.ts b/src/config/routes.ts
index 909e34db7a..0509085fa5 100644
--- a/src/config/routes.ts
+++ b/src/config/routes.ts
@@ -45,6 +45,7 @@ export const AppRoutes = {
share: {
safeApp: '/share/safe-app',
},
+ stake: '/stake',
transactions: {
tx: '/transactions/tx',
queue: '/transactions/queue',
diff --git a/src/utils/chains.ts b/src/utils/chains.ts
index 4d3940839e..10e8c721d1 100644
--- a/src/utils/chains.ts
+++ b/src/utils/chains.ts
@@ -34,11 +34,13 @@ export enum FEATURES {
RELAY_NATIVE_SWAPS = 'RELAY_NATIVE_SWAPS',
ZODIAC_ROLES = 'ZODIAC_ROLES',
SAFE_141 = 'SAFE_141',
+ STAKE_TEASER = 'STAKE_TEASER',
}
export const FeatureRoutes = {
[AppRoutes.apps.index]: FEATURES.SAFE_APPS,
[AppRoutes.swap]: FEATURES.NATIVE_SWAPS,
+ [AppRoutes.stake]: FEATURES.STAKE_TEASER,
[AppRoutes.balances.nfts]: FEATURES.ERC721,
[AppRoutes.settings.notifications]: FEATURES.PUSH_NOTIFICATIONS,
}
From 41e9784f802c341779297718d1bc3af9656ebaad Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Wed, 11 Sep 2024 16:22:37 +0200
Subject: [PATCH 60/81] Fix: hide SAP and Swaps if geoblocked (#4148)
---
src/components/common/Header/index.tsx | 7 +++----
src/components/dashboard/index.tsx | 24 ++++++++++++++++--------
src/hooks/useSafeTokenEnabled.ts | 10 ++++++++++
3 files changed, 29 insertions(+), 12 deletions(-)
create mode 100644 src/hooks/useSafeTokenEnabled.ts
diff --git a/src/components/common/Header/index.tsx b/src/components/common/Header/index.tsx
index 629c62f399..cfa880fd6b 100644
--- a/src/components/common/Header/index.tsx
+++ b/src/components/common/Header/index.tsx
@@ -8,10 +8,9 @@ import classnames from 'classnames'
import css from './styles.module.css'
import ConnectWallet from '@/components/common/ConnectWallet'
import NetworkSelector from '@/components/common/NetworkSelector'
-import SafeTokenWidget, { getSafeTokenAddress } from '@/components/common/SafeTokenWidget'
+import SafeTokenWidget from '@/components/common/SafeTokenWidget'
import NotificationCenter from '@/components/notification-center/NotificationCenter'
import { AppRoutes } from '@/config/routes'
-import useChainId from '@/hooks/useChainId'
import SafeLogo from '@/public/images/logo.svg'
import SafeLogoMobile from '@/public/images/logo-no-text.svg'
import Link from 'next/link'
@@ -22,6 +21,7 @@ import { FEATURES } from '@/utils/chains'
import { useHasFeature } from '@/hooks/useChains'
import Track from '@/components/common/Track'
import { OVERVIEW_EVENTS, OVERVIEW_LABELS } from '@/services/analytics'
+import { useSafeTokenEnabled } from '@/hooks/useSafeTokenEnabled'
type HeaderProps = {
onMenuToggle?: Dispatch>
@@ -37,9 +37,8 @@ function getLogoLink(router: ReturnType): Url {
}
const Header = ({ onMenuToggle, onBatchToggle }: HeaderProps): ReactElement => {
- const chainId = useChainId()
const safeAddress = useSafeAddress()
- const showSafeToken = safeAddress && !!getSafeTokenAddress(chainId)
+ const showSafeToken = useSafeTokenEnabled()
const router = useRouter()
const enableWc = useHasFeature(FEATURES.NATIVE_WALLETCONNECT)
diff --git a/src/components/dashboard/index.tsx b/src/components/dashboard/index.tsx
index fa480c931f..4235cacf4a 100644
--- a/src/components/dashboard/index.tsx
+++ b/src/components/dashboard/index.tsx
@@ -1,6 +1,6 @@
import FirstSteps from '@/components/dashboard/FirstSteps'
import useSafeInfo from '@/hooks/useSafeInfo'
-import type { ReactElement } from 'react'
+import { type ReactElement } from 'react'
import dynamic from 'next/dynamic'
import { Grid } from '@mui/material'
import PendingTxsList from '@/components/dashboard/PendingTxs/PendingTxsList'
@@ -16,13 +16,17 @@ import { useHasFeature } from '@/hooks/useChains'
import { FEATURES } from '@/utils/chains'
import css from './styles.module.css'
import SwapWidget from '@/features/swap/components/SwapWidget'
+import useIsSwapFeatureEnabled from '@/features/swap/hooks/useIsSwapFeatureEnabled'
+import { useSafeTokenEnabled } from '@/hooks/useSafeTokenEnabled'
const RecoveryHeader = dynamic(() => import('@/features/recovery/components/RecoveryHeader'))
const Dashboard = (): ReactElement => {
const { safe } = useSafeInfo()
const showSafeApps = useHasFeature(FEATURES.SAFE_APPS)
- const isSAPBannerEnabled = useHasFeature(FEATURES.SAP_BANNER)
+ const isSafeTokenEnabled = useSafeTokenEnabled()
+ const isSwapFeatureEnabled = useIsSwapFeatureEnabled()
+ const isSAPBannerEnabled = useHasFeature(FEATURES.SAP_BANNER) && isSafeTokenEnabled
const supportsRecovery = useIsRecoverySupported()
const [recovery] = useRecovery()
const showRecoveryWidget = supportsRecovery && !recovery
@@ -42,13 +46,17 @@ const Dashboard = (): ReactElement => {
{safe.deployed && (
<>
-
-
-
+ {isSwapFeatureEnabled && (
+
+
+
+ )}
-
-
-
+ {isSAPBannerEnabled && (
+
+
+
+ )}
diff --git a/src/hooks/useSafeTokenEnabled.ts b/src/hooks/useSafeTokenEnabled.ts
new file mode 100644
index 0000000000..de25364c60
--- /dev/null
+++ b/src/hooks/useSafeTokenEnabled.ts
@@ -0,0 +1,10 @@
+import { useContext } from 'react'
+import { GeoblockingContext } from '@/components/common/GeoblockingProvider'
+import useSafeInfo from './useSafeInfo'
+import { getSafeTokenAddress } from '@/components/common/SafeTokenWidget'
+
+export function useSafeTokenEnabled(): boolean {
+ const isBlockedCountry = useContext(GeoblockingContext)
+ const { safe, safeLoaded } = useSafeInfo()
+ return !isBlockedCountry && safeLoaded && !!getSafeTokenAddress(safe.chainId)
+}
From ab3871bfa819afeb0bec4622d04b0c2e2eae0209 Mon Sep 17 00:00:00 2001
From: Manuel Gellfart
Date: Wed, 11 Sep 2024 16:59:40 +0200
Subject: [PATCH 61/81] feat: blockaid integration (#4029)
* feat: blockaid integration
- exchanges redefine for blockaid
- redesigns warning component
* feat: better error handling
* fix: adjust design for errors
* feat: add powered by footer
* feat: add more chains, code cleanup
* fix: change URL and auth header
* fix: update .env variable in build.yml
* fix: throw error if validation is missing
* fix: loading state of blockaid block
* tests: adjust mock
---
.env.example | 4 +-
.github/workflows/build/action.yml | 2 +-
public/images/transactions/blockaid-icon.svg | 17 +
.../RecoverAccountFlowReview.tsx | 4 +-
.../tx-flow/flows/SignMessage/SignMessage.tsx | 4 +-
.../tx/SignOrExecuteForm/TxChecks.tsx | 7 -
src/components/tx/SignOrExecuteForm/index.tsx | 10 +-
.../tx/security/SecurityWarnings.tsx | 2 -
.../BlockaidBalanceChange.tsx} | 103 +--
.../tx/security/blockaid/BlockaidHint.tsx | 14 +
.../blockaid/__tests__/useBlockaid.test.ts | 244 +++++++
src/components/tx/security/blockaid/index.tsx | 228 +++++++
.../{redefine => blockaid}/styles.module.css | 23 +-
.../tx/security/blockaid/useBlockaid.ts | 58 ++
.../tx/security/redefine/RedefineHint.tsx | 52 --
src/components/tx/security/redefine/index.tsx | 207 ------
.../tx/security/redefine/useRedefine.test.ts | 330 ----------
.../tx/security/redefine/useRedefine.ts | 146 -----
.../tx/security/shared/TxSecurityContext.tsx | 67 +-
src/components/tx/security/utils.ts | 47 ++
src/config/constants.ts | 6 +-
src/services/analytics/events/modals.ts | 5 +
.../security/modules/BlockaidModule/index.ts | 165 +++++
.../security/modules/BlockaidModule/types.ts | 619 ++++++++++++++++++
.../security/modules/RedefineModule/index.ts | 178 -----
25 files changed, 1541 insertions(+), 1001 deletions(-)
create mode 100644 public/images/transactions/blockaid-icon.svg
rename src/components/tx/security/{redefine/RedefineBalanceChange.tsx => blockaid/BlockaidBalanceChange.tsx} (62%)
create mode 100644 src/components/tx/security/blockaid/BlockaidHint.tsx
create mode 100644 src/components/tx/security/blockaid/__tests__/useBlockaid.test.ts
create mode 100644 src/components/tx/security/blockaid/index.tsx
rename src/components/tx/security/{redefine => blockaid}/styles.module.css (75%)
create mode 100644 src/components/tx/security/blockaid/useBlockaid.ts
delete mode 100644 src/components/tx/security/redefine/RedefineHint.tsx
delete mode 100644 src/components/tx/security/redefine/index.tsx
delete mode 100644 src/components/tx/security/redefine/useRedefine.test.ts
delete mode 100644 src/components/tx/security/redefine/useRedefine.ts
create mode 100644 src/components/tx/security/utils.ts
create mode 100644 src/services/security/modules/BlockaidModule/index.ts
create mode 100644 src/services/security/modules/BlockaidModule/types.ts
delete mode 100644 src/services/security/modules/RedefineModule/index.ts
diff --git a/.env.example b/.env.example
index ab53f2b047..a4f3101a82 100644
--- a/.env.example
+++ b/.env.example
@@ -38,8 +38,8 @@ NEXT_PUBLIC_FIREBASE_VAPID_KEY_PRODUCTION=
NEXT_PUBLIC_FIREBASE_OPTIONS_STAGING=
NEXT_PUBLIC_FIREBASE_VAPID_KEY_STAGING=
-# Redefine
-NEXT_PUBLIC_REDEFINE_API=
+# Blockaid
+NEXT_PUBLIC_BLOCKAID_CLIENT_ID
# Social Login
NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_STAGING=
diff --git a/.github/workflows/build/action.yml b/.github/workflows/build/action.yml
index 6b8ef9d45e..ba6ad94d7e 100644
--- a/.github/workflows/build/action.yml
+++ b/.github/workflows/build/action.yml
@@ -51,7 +51,7 @@ runs:
NEXT_PUBLIC_SAFE_RELAY_SERVICE_URL_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_PRODUCTION }}
NEXT_PUBLIC_SAFE_RELAY_SERVICE_URL_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SAFE_GELATO_RELAY_SERVICE_URL_STAGING }}
NEXT_PUBLIC_IS_OFFICIAL_HOST: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_IS_OFFICIAL_HOST }}
- NEXT_PUBLIC_REDEFINE_API: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_REDEFINE_API }}
+ NEXT_PUBLIC_BLOCKAID_CLIENT_ID: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_BLOCKAID_CLIENT_ID }}
NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_STAGING: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_STAGING }}
NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_SOCIAL_WALLET_OPTIONS_PRODUCTION }}
NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION: ${{ fromJSON(inputs.secrets).NEXT_PUBLIC_FIREBASE_OPTIONS_PRODUCTION }}
diff --git a/public/images/transactions/blockaid-icon.svg b/public/images/transactions/blockaid-icon.svg
new file mode 100644
index 0000000000..7c66a098f9
--- /dev/null
+++ b/public/images/transactions/blockaid-icon.svg
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/components/tx-flow/flows/RecoverAccount/RecoverAccountFlowReview.tsx b/src/components/tx-flow/flows/RecoverAccount/RecoverAccountFlowReview.tsx
index e62f7fe994..e057ea107f 100644
--- a/src/components/tx-flow/flows/RecoverAccount/RecoverAccountFlowReview.tsx
+++ b/src/components/tx-flow/flows/RecoverAccount/RecoverAccountFlowReview.tsx
@@ -8,7 +8,6 @@ import useSafeInfo from '@/hooks/useSafeInfo'
import { getRecoveryProposalTransactions } from '@/features/recovery/services/transaction'
import DecodedTx from '@/components/tx/DecodedTx'
import ErrorMessage from '@/components/tx/ErrorMessage'
-import { RedefineBalanceChanges } from '@/components/tx/security/redefine/RedefineBalanceChange'
import ConfirmationTitle, { ConfirmationTitleTypes } from '@/components/tx/SignOrExecuteForm/ConfirmationTitle'
import TxChecks from '@/components/tx/SignOrExecuteForm/TxChecks'
import useDecodeTx from '@/hooks/useDecodeTx'
@@ -33,6 +32,7 @@ import { isWalletRejection } from '@/utils/wallets'
import WalletRejectionError from '@/components/tx/SignOrExecuteForm/WalletRejectionError'
import commonCss from '@/components/tx-flow/common/styles.module.css'
+import { BlockaidBalanceChanges } from '@/components/tx/security/blockaid/BlockaidBalanceChange'
import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
export function RecoverAccountFlowReview({ params }: { params: RecoverAccountFlowProps }): ReactElement | null {
@@ -129,7 +129,7 @@ export function RecoverAccountFlowReview({ params }: { params: RecoverAccountFlo
-
+
diff --git a/src/components/tx-flow/flows/SignMessage/SignMessage.tsx b/src/components/tx-flow/flows/SignMessage/SignMessage.tsx
index 603bb4918e..a976e23a7b 100644
--- a/src/components/tx-flow/flows/SignMessage/SignMessage.tsx
+++ b/src/components/tx-flow/flows/SignMessage/SignMessage.tsx
@@ -42,7 +42,6 @@ import { trackEvent } from '@/services/analytics'
import { TX_EVENTS, TX_TYPES } from '@/services/analytics/events/transactions'
import { SafeTxContext } from '../../SafeTxProvider'
import RiskConfirmationError from '@/components/tx/SignOrExecuteForm/RiskConfirmationError'
-import { Redefine } from '@/components/tx/security/redefine'
import { TxSecurityContext } from '@/components/tx/security/shared/TxSecurityContext'
import { isBlindSigningPayload, isEIP712TypedData } from '@/utils/safe-messages'
import ApprovalEditor from '@/components/tx/ApprovalEditor'
@@ -55,6 +54,7 @@ import { AppRoutes } from '@/config/routes'
import { useRouter } from 'next/router'
import MsgShareLink from '@/components/safe-messages/MsgShareLink'
import LinkIcon from '@/public/images/messages/link.svg'
+import { Blockaid } from '@/components/tx/security/blockaid'
import CheckWallet from '@/components/common/CheckWallet'
import NetworkWarning from '@/components/new-safe/create/NetworkWarning'
@@ -317,7 +317,7 @@ const SignMessage = ({ message, safeAppId, requestId }: ProposeProps | ConfirmPr
-
+
diff --git a/src/components/tx/SignOrExecuteForm/TxChecks.tsx b/src/components/tx/SignOrExecuteForm/TxChecks.tsx
index 3d9bd6525c..d997c865b0 100644
--- a/src/components/tx/SignOrExecuteForm/TxChecks.tsx
+++ b/src/components/tx/SignOrExecuteForm/TxChecks.tsx
@@ -6,7 +6,6 @@ import { TxSimulation, TxSimulationMessage } from '@/components/tx/security/tend
import TxCard from '@/components/tx-flow/common/TxCard'
import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider'
import { Box, Typography } from '@mui/material'
-import { Redefine, RedefineMessage } from '@/components/tx/security/redefine'
import css from './styles.module.css'
@@ -29,12 +28,6 @@ const TxChecks = ({ executionOwner }: { executionOwner?: string }): ReactElement
-
-
-
-
-
-
)
}
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index 55f4ea1456..e830e75db9 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -16,9 +16,7 @@ import TxCard from '@/components/tx-flow/common/TxCard'
import ConfirmationTitle, { ConfirmationTitleTypes } from '@/components/tx/SignOrExecuteForm/ConfirmationTitle'
import { useAppSelector } from '@/store'
import { selectSettings } from '@/store/settingsSlice'
-import { RedefineBalanceChanges } from '../security/redefine/RedefineBalanceChange'
import UnknownContractError from './UnknownContractError'
-import RiskConfirmationError from './RiskConfirmationError'
import useDecodeTx from '@/hooks/useDecodeTx'
import { ErrorBoundary } from '@sentry/react'
import ApprovalEditor from '../ApprovalEditor'
@@ -34,6 +32,9 @@ import SwapOrderConfirmationView from '@/features/swap/components/SwapOrderConfi
import { isSettingTwapFallbackHandler } from '@/features/swap/helpers/utils'
import { TwapFallbackHandlerWarning } from '@/features/swap/components/TwapFallbackHandlerWarning'
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
+import { BlockaidBalanceChanges } from '../security/blockaid/BlockaidBalanceChange'
+import { Blockaid } from '../security/blockaid'
+
import TxData from '@/components/transactions/TxDetails/TxData'
import { useApprovalInfos } from '../ApprovalEditor/hooks/useApprovalInfos'
@@ -175,8 +176,7 @@ export const SignOrExecuteForm = ({
/>
)}
-
- {!isCounterfactualSafe && !props.isRejection && }
+ {!isCounterfactualSafe && !props.isRejection && }
{!isCounterfactualSafe && !props.isRejection && }
@@ -201,7 +201,7 @@ export const SignOrExecuteForm = ({
-
+
{isCounterfactualSafe && !isDelegate && (
diff --git a/src/components/tx/security/SecurityWarnings.tsx b/src/components/tx/security/SecurityWarnings.tsx
index f78c9fde22..92a16d0342 100644
--- a/src/components/tx/security/SecurityWarnings.tsx
+++ b/src/components/tx/security/SecurityWarnings.tsx
@@ -1,9 +1,7 @@
-import { RedefineMessage } from './redefine'
import { TxSimulationMessage } from './tenderly'
const SecurityWarnings = () => (
<>
-
>
)
diff --git a/src/components/tx/security/redefine/RedefineBalanceChange.tsx b/src/components/tx/security/blockaid/BlockaidBalanceChange.tsx
similarity index 62%
rename from src/components/tx/security/redefine/RedefineBalanceChange.tsx
rename to src/components/tx/security/blockaid/BlockaidBalanceChange.tsx
index 2d6a50c4be..71bce871cb 100644
--- a/src/components/tx/security/redefine/RedefineBalanceChange.tsx
+++ b/src/components/tx/security/blockaid/BlockaidBalanceChange.tsx
@@ -3,10 +3,8 @@ import TokenIcon from '@/components/common/TokenIcon'
import useBalances from '@/hooks/useBalances'
import useChainId from '@/hooks/useChainId'
import { useHasFeature } from '@/hooks/useChains'
-import { type RedefineModuleResponse } from '@/services/security/modules/RedefineModule'
import { sameAddress } from '@/utils/addresses'
import { FEATURES } from '@/utils/chains'
-import { formatVisualAmount } from '@/utils/formatters'
import { Box, Chip, CircularProgress, Grid, SvgIcon, Tooltip, Typography } from '@mui/material'
import { TokenType } from '@safe-global/safe-gateway-typescript-sdk'
import { ErrorBoundary } from '@sentry/react'
@@ -19,63 +17,75 @@ import ExternalLink from '@/components/common/ExternalLink'
import { REDEFINE_ARTICLE } from '@/config/constants'
import css from './styles.module.css'
+import type {
+ AssetDiff,
+ Erc1155Diff,
+ Erc1155TokenDetails,
+ Erc20Diff,
+ Erc721Diff,
+ Erc721TokenDetails,
+ GeneralAssetDiff,
+ NativeDiff,
+} from '@/services/security/modules/BlockaidModule/types'
+import { formatAmount } from '@/utils/formatNumber'
-const FungibleBalanceChange = ({
- change,
-}: {
- change: NonNullable['in' | 'out'][number] & { type: 'ERC20' | 'NATIVE' }
-}) => {
+const FungibleBalanceChange = ({ change, asset }: { asset: AssetDiff['asset']; change: Erc20Diff | NativeDiff }) => {
const { balances } = useBalances()
-
- const logoUri = balances.items.find((item) => {
- return change.type === 'NATIVE'
- ? item.tokenInfo.type === TokenType.NATIVE_TOKEN
- : sameAddress(item.tokenInfo.address, change.address)
- })?.tokenInfo.logoUri
+ const logoUri =
+ asset.logo_url ??
+ balances.items.find((item) => {
+ return asset.type === 'NATIVE'
+ ? item.tokenInfo.type === TokenType.NATIVE_TOKEN
+ : sameAddress(item.tokenInfo.address, asset.address)
+ })?.tokenInfo.logoUri
return (
<>
- {formatVisualAmount(change.amount.value, change.decimals)}
+ {change.value ? formatAmount(change.value) : 'unknown'}
-
+
- {change.symbol}
+ {asset.symbol}
-
+
>
)
}
const NFTBalanceChange = ({
change,
+ asset,
}: {
- change: NonNullable['in' | 'out'][number] & { type: 'ERC721' }
+ asset: Erc721TokenDetails | Erc1155TokenDetails
+ change: Erc721Diff | Erc1155Diff
}) => {
const chainId = useChainId()
return (
<>
- {change.symbol ? (
+ {asset.symbol ? (
- {change.symbol}
+ {asset.symbol}
) : (
)}
- #{change.tokenId}
+ #{Number(change.token_id)}
@@ -84,27 +94,36 @@ const NFTBalanceChange = ({
}
const BalanceChange = ({
- change,
+ asset,
positive = false,
+ diff,
}: {
- change: NonNullable['in' | 'out'][number]
+ asset: NonNullable
positive?: boolean
+ diff: GeneralAssetDiff
}) => {
return (
{positive ? : }
- {change.type === 'ERC721' ? : }
+ {asset.type === 'ERC721' || asset.type === 'ERC1155' ? (
+
+ ) : (
+
+ )}
)
}
-
const BalanceChanges = () => {
- const { balanceChange, isLoading } = useContext(TxSecurityContext)
- const totalBalanceChanges = balanceChange ? balanceChange.in.length + balanceChange.out.length : 0
+ const { blockaidResponse } = useContext(TxSecurityContext)
+ const { isLoading, balanceChange, error } = blockaidResponse ?? {}
+
+ const totalBalanceChanges = balanceChange
+ ? balanceChange.reduce((prev, current) => prev + current.in.length + current.out.length, 0)
+ : 0
- if (isLoading && !balanceChange) {
+ if (isLoading) {
return (
{
)
}
-
+ if (error) {
+ return (
+
+ Could not calculate balance changes.
+
+ )
+ }
if (totalBalanceChanges === 0) {
return (
@@ -131,18 +156,22 @@ const BalanceChanges = () => {
return (
<>
- {balanceChange?.in.map((change, idx) => (
-
- ))}
- {balanceChange?.out.map((change, idx) => (
-
+ {balanceChange?.map((change, assetIdx) => (
+ <>
+ {change.in.map((diff, changeIdx) => (
+
+ ))}
+ {change.out.map((diff, changeIdx) => (
+
+ ))}
+ >
))}
>
)
}
-export const RedefineBalanceChanges = () => {
+export const BlockaidBalanceChanges = () => {
const isFeatureEnabled = useHasFeature(FEATURES.RISK_MITIGATION)
if (!isFeatureEnabled) {
diff --git a/src/components/tx/security/blockaid/BlockaidHint.tsx b/src/components/tx/security/blockaid/BlockaidHint.tsx
new file mode 100644
index 0000000000..e006c222ad
--- /dev/null
+++ b/src/components/tx/security/blockaid/BlockaidHint.tsx
@@ -0,0 +1,14 @@
+import { type SecuritySeverity } from '@/services/security/modules/types'
+import { List, ListItem, Typography } from '@mui/material'
+
+export const BlockaidHint = ({ severity, warnings }: { severity: SecuritySeverity; warnings: string[] }) => {
+ return (
+
+ {warnings.map((warning) => (
+
+ {warning}
+
+ ))}
+
+ )
+}
diff --git a/src/components/tx/security/blockaid/__tests__/useBlockaid.test.ts b/src/components/tx/security/blockaid/__tests__/useBlockaid.test.ts
new file mode 100644
index 0000000000..5f7d407c5d
--- /dev/null
+++ b/src/components/tx/security/blockaid/__tests__/useBlockaid.test.ts
@@ -0,0 +1,244 @@
+import * as useChains from '@/hooks/useChains'
+import { type ConnectedWallet } from '@/hooks/wallets/useOnboard'
+import * as useWallet from '@/hooks/wallets/useWallet'
+import { SecuritySeverity } from '@/services/security/modules/types'
+import { eip712TypedDataBuilder } from '@/tests/builders/messages'
+import { safeTxBuilder } from '@/tests/builders/safeTx'
+import { parseUnits, toBeHex } from 'ethers'
+import { useBlockaid } from '../useBlockaid'
+import { type AssetDiff, type TransactionScanResponse } from '@/services/security/modules/BlockaidModule/types'
+import { faker } from '@faker-js/faker/locale/af_ZA'
+import useSafeInfo from '@/hooks/useSafeInfo'
+import { safeInfoBuilder } from '@/tests/builders/safe'
+import { CLASSIFICATION_MAPPING, REASON_MAPPING } from '..'
+import { renderHook, waitFor } from '@/tests/test-utils'
+
+const setupFetchStub = (data: any) => (_url: string) => {
+ return Promise.resolve({
+ json: () => Promise.resolve(data),
+ status: 200,
+ ok: true,
+ })
+}
+
+// Mock BLOCKAID_API
+jest.mock('@/config/constants', () => ({
+ ...jest.requireActual('@/config/constants'),
+ BLOCKAID_CLIENT_ID: 'some-client-id',
+}))
+
+enum TEST_CASES {
+ MESSAGE = 'EIP 712 Message',
+ TRANSACTION = 'SafeTransaction',
+}
+
+jest.mock('@/hooks/useSafeInfo')
+
+const mockUseSafeInfo = useSafeInfo as jest.MockedFunction
+
+describe.each([TEST_CASES.MESSAGE, TEST_CASES.TRANSACTION])('useBlockaid for %s', (testCase) => {
+ let mockUseWallet: jest.SpyInstance
+
+ const mockPayload = testCase === TEST_CASES.TRANSACTION ? safeTxBuilder().build() : eip712TypedDataBuilder().build()
+
+ const mockSafeInfo = safeInfoBuilder().with({ chainId: '1' }).build()
+
+ beforeEach(() => {
+ jest.resetAllMocks()
+ jest.useFakeTimers()
+ mockUseWallet = jest.spyOn(useWallet, 'default')
+ mockUseWallet.mockImplementation(() => null)
+ mockUseSafeInfo.mockReturnValue({
+ safe: { ...mockSafeInfo, deployed: true },
+ safeAddress: mockSafeInfo.address.value,
+ safeLoaded: true,
+ safeLoading: false,
+ })
+
+ global.fetch = jest.fn()
+ })
+
+ it('should return undefined without data', async () => {
+ const { result } = renderHook(() => useBlockaid(undefined))
+
+ await waitFor(() => {
+ expect(result.current[0]).toBeUndefined()
+ expect(result.current[1]).toBeUndefined()
+ expect(result.current[2]).toBeFalsy()
+ })
+ })
+
+ it('should return undefined without connected wallet', async () => {
+ const { result } = renderHook(() => useBlockaid(mockPayload))
+
+ await waitFor(() => {
+ expect(result.current[0]).toBeUndefined()
+ expect(result.current[1]).toBeUndefined()
+ expect(result.current[2]).toBeFalsy()
+ })
+ })
+
+ it('should return undefined without feature enabled', async () => {
+ const walletAddress = toBeHex('0x1', 20)
+
+ mockUseWallet.mockImplementation(() => ({
+ address: walletAddress,
+ chainId: '1',
+ label: 'Testwallet',
+ provider: {} as any,
+ }))
+
+ jest.spyOn(useChains, 'useHasFeature').mockReturnValue(false)
+
+ const { result } = renderHook(() => useBlockaid(mockPayload))
+
+ await waitFor(() => {
+ expect(result.current[0]).toBeUndefined()
+ expect(result.current[1]).toEqual(undefined)
+ expect(result.current[2]).toBeFalsy()
+ })
+ })
+
+ it('should handle request errors', async () => {
+ const walletAddress = toBeHex('0x1', 20)
+
+ mockUseWallet.mockImplementation(() => ({
+ address: walletAddress,
+ chainId: '1',
+ label: 'Testwallet',
+ provider: {} as any,
+ }))
+
+ jest.spyOn(useChains, 'useHasFeature').mockReturnValue(true)
+
+ const mockFetch = jest.spyOn(global, 'fetch')
+ mockFetch.mockImplementation(() => Promise.reject({ message: '403 not authorized' }))
+
+ const { result } = renderHook(() => useBlockaid(mockPayload))
+
+ await waitFor(() => {
+ expect(result.current[0]).toBeUndefined()
+ expect(result.current[1]).toEqual(new Error('Unavailable'))
+ expect(result.current[2]).toBeFalsy()
+ })
+ })
+
+ it('should handle failed simulations', async () => {
+ const walletAddress = toBeHex('0x1', 20)
+
+ mockUseWallet.mockImplementation(() => ({
+ address: walletAddress,
+ chainId: '1',
+ label: 'Testwallet',
+ provider: {} as any,
+ }))
+
+ jest.spyOn(useChains, 'useHasFeature').mockReturnValue(true)
+
+ const mockBlockaidResponse: TransactionScanResponse = {
+ chain: '1',
+ block: faker.number.int().toString(),
+ simulation: {
+ status: 'Error',
+ error: 'Simulation failed: GS13',
+ },
+ validation: {
+ status: 'Success',
+ features: [],
+ result_type: 'Benign',
+ classification: '',
+ description: '',
+ reason: '',
+ },
+ }
+
+ global.fetch = jest.fn().mockImplementation(setupFetchStub(mockBlockaidResponse))
+
+ const { result } = renderHook(() => useBlockaid(mockPayload))
+
+ await waitFor(() => {
+ expect(result.current[0]).toBeDefined()
+ expect(result.current[1]).toEqual(new Error('Simulation failed'))
+ expect(result.current[2]).toBeFalsy()
+ })
+ })
+
+ it('should return the redefine issues and balance change', async () => {
+ const walletAddress = toBeHex('0x1', 20)
+
+ const accountDiff = {
+ asset: {
+ address: faker.finance.ethereumAddress(),
+ decimals: 18,
+ type: 'ERC20',
+ name: 'Safe Token',
+ symbol: 'SAFE',
+ },
+ out: [
+ {
+ raw_value: parseUnits('1', 18).toString(),
+ value: '1',
+ },
+ ],
+ in: [],
+ } as AssetDiff
+
+ const mockBlockaidResponse: TransactionScanResponse = {
+ chain: '1',
+ block: faker.number.int().toString(),
+ simulation: {
+ status: 'Success',
+ assets_diffs: {
+ [mockSafeInfo.address.value]: [accountDiff],
+ },
+ account_summary: {
+ assets_diffs: [accountDiff],
+ exposures: [],
+ total_usd_diff: {
+ in: '0',
+ out: '0',
+ total: '0',
+ },
+ total_usd_exposure: {},
+ },
+ address_details: {},
+ exposures: {},
+ total_usd_diff: {},
+ total_usd_exposure: {},
+ },
+ validation: {
+ status: 'Success',
+ features: [],
+ result_type: 'Malicious',
+ classification: Object.keys(CLASSIFICATION_MAPPING)[0],
+ description: 'Malicious tx detected',
+ reason: Object.keys(REASON_MAPPING)[0],
+ },
+ }
+
+ mockUseWallet.mockImplementation(() => ({
+ address: walletAddress,
+ chainId: '1',
+ label: 'Testwallet',
+ provider: {} as any,
+ }))
+
+ jest.spyOn(useChains, 'useHasFeature').mockReturnValue(true)
+
+ global.fetch = jest.fn().mockImplementation(setupFetchStub(mockBlockaidResponse))
+
+ const mockFetch = jest.spyOn(global, 'fetch')
+ const { result } = renderHook(() => useBlockaid(mockPayload))
+
+ await waitFor(() => {
+ expect(result.current[1]).toBeUndefined()
+ expect(result.current[0]).toBeDefined()
+ const response = result.current[0]
+ expect(response?.severity).toEqual(SecuritySeverity.HIGH)
+ expect(response?.payload?.issues).toHaveLength(0)
+ expect(response?.payload?.balanceChange[0]).toEqual(accountDiff)
+ expect(result.current[2]).toBeFalsy()
+ expect(mockFetch).toHaveBeenCalledTimes(1)
+ })
+ })
+})
diff --git a/src/components/tx/security/blockaid/index.tsx b/src/components/tx/security/blockaid/index.tsx
new file mode 100644
index 0000000000..f1c18f9736
--- /dev/null
+++ b/src/components/tx/security/blockaid/index.tsx
@@ -0,0 +1,228 @@
+import { useContext } from 'react'
+import { TxSecurityContext, type TxSecurityContextProps } from '@/components/tx/security/shared/TxSecurityContext'
+import groupBy from 'lodash/groupBy'
+import { Alert, AlertTitle, Box, Checkbox, FormControlLabel, Stack, Typography } from '@mui/material'
+import { FEATURES } from '@/utils/chains'
+import { useHasFeature } from '@/hooks/useChains'
+import { ErrorBoundary } from '@sentry/react'
+import css from './styles.module.css'
+
+import Track from '@/components/common/Track'
+import { MODALS_EVENTS } from '@/services/analytics'
+
+import BlockaidIcon from '@/public/images/transactions/blockaid-icon.svg'
+import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider'
+import { type SecurityWarningProps, mapSecuritySeverity } from '../utils'
+import { BlockaidHint } from './BlockaidHint'
+import Warning from '@/public/images/notifications/alert.svg'
+import { SecuritySeverity } from '@/services/security/modules/types'
+
+export const REASON_MAPPING: Record = {
+ raw_ether_transfer: 'transfers native currency',
+ signature_farming: 'is a raw signed transaction',
+ transfer_farming: 'transfers tokens',
+ approval_farming: 'approves erc20 tokens',
+ set_approval_for_all: 'approves all tokens of the account',
+ permit_farming: 'authorizes access or permissions',
+ seaport_farming: 'authorizes transfer of assets via Opeansea marketplace',
+ blur_farming: 'authorizes transfer of assets via Blur marketplace',
+ delegatecall_execution: 'involves a delegate call',
+}
+
+export const CLASSIFICATION_MAPPING: Record = {
+ known_malicious: 'to a known malicious address',
+ unverified_contract: 'to an unverified contract',
+ new_address: 'to a new address',
+ untrusted_address: 'to an untrusted address',
+ address_poisoning: 'to a poisoned address',
+ losing_mint: 'resulting in a mint for a new token with a significantly higher price than the known price',
+ losing_assets: 'resulting in a loss of assets without any compensation',
+ losing_trade: 'resulting in a losing trade',
+ drainer_contract: 'to a known drainer contract',
+ user_mistake: 'resulting in a loss of assets due to an innocent mistake',
+ gas_farming_attack: 'resulting in a waste of the account address’ gas to generate tokens for a scammer',
+ other: 'resulting in a malicious outcome',
+}
+
+const BlockaidResultWarning = ({
+ blockaidResponse,
+ severityProps,
+ needsRiskConfirmation,
+ isRiskConfirmed,
+ isTransaction,
+ toggleConfirmation,
+}: {
+ blockaidResponse?: TxSecurityContextProps['blockaidResponse']
+ severityProps?: SecurityWarningProps
+ needsRiskConfirmation: boolean
+ isRiskConfirmed: boolean
+ isTransaction: boolean
+ toggleConfirmation: () => void
+}) => {
+ return (
+
+ {blockaidResponse && blockaidResponse.severity !== SecuritySeverity.NONE && (
+ <>
+ }
+ className={css.customAlert}
+ sx={
+ needsRiskConfirmation
+ ? {
+ borderBottomLeftRadius: '0px',
+ borderBottomRightRadius: '0px',
+ }
+ : undefined
+ }
+ >
+
+
+
+
+
+ {needsRiskConfirmation && (
+
+
+
+ I understand the risks and would like to sign this {isTransaction ? 'transaction' : 'message'}
+
+ }
+ control={ }
+ />
+
+
+ )}
+
+
+ Powered by
+
+
+
+ >
+ )}
+
+ )
+}
+
+const ResultDescription = ({
+ description,
+ reason,
+ classification,
+}: {
+ description: string | undefined
+ reason: string | undefined
+ classification: string | undefined
+}) => {
+ let text: string | undefined = ''
+ if (reason && classification && REASON_MAPPING[reason] && CLASSIFICATION_MAPPING[classification]) {
+ text = `The transaction ${REASON_MAPPING[reason]} ${CLASSIFICATION_MAPPING[classification]}.`
+ } else {
+ text = description
+ }
+
+ return (
+
+ {text ?? 'The transaction is malicious.'}
+
+ )
+}
+
+const BlockaidError = () => {
+ return (
+ } className={css.customAlert}>
+
+
+ Proceed with caution
+
+
+
+ The transaction could not be checked for security alerts. Verify the details and addresses before proceeding.
+
+
+
+ )
+}
+
+export const Blockaid = () => {
+ const isFeatureEnabled = useHasFeature(FEATURES.RISK_MITIGATION)
+
+ if (!isFeatureEnabled) {
+ return null
+ }
+
+ return (
+ Error showing scan result }>
+
+
+ )
+}
+
+const BlockaidWarning = () => {
+ const { blockaidResponse, setIsRiskConfirmed, needsRiskConfirmation, isRiskConfirmed, isRiskIgnored } =
+ useContext(TxSecurityContext)
+ const { severity, warnings, isLoading, error } = blockaidResponse ?? {}
+
+ const { safeTx } = useContext(SafeTxContext)
+
+ // We either scan a tx or a message if tx is undefined
+ const isTransaction = !!safeTx
+
+ const severityProps = severity !== undefined ? mapSecuritySeverity[severity] : undefined
+
+ const toggleConfirmation = () => {
+ setIsRiskConfirmed((prev) => !prev)
+ }
+
+ if (error) {
+ return
+ }
+
+ if (isLoading || !blockaidResponse || !blockaidResponse.severity) {
+ return null
+ }
+
+ return (
+
+ )
+}
+
+export const BlockaidMessage = () => {
+ const { blockaidResponse } = useContext(TxSecurityContext)
+ if (!blockaidResponse) {
+ return null
+ }
+
+ const { warnings } = blockaidResponse
+
+ /* Evaluate security warnings */
+ const groupedShownWarnings = groupBy(warnings, (warning) => warning.severity)
+ const sortedSeverities = Object.keys(groupedShownWarnings).sort((a, b) => (Number(a) < Number(b) ? 1 : -1))
+
+ if (sortedSeverities.length === 0) return null
+
+ return (
+
+ {sortedSeverities.map((key) => (
+ warning.description)}
+ />
+ ))}
+
+ )
+}
diff --git a/src/components/tx/security/redefine/styles.module.css b/src/components/tx/security/blockaid/styles.module.css
similarity index 75%
rename from src/components/tx/security/redefine/styles.module.css
rename to src/components/tx/security/blockaid/styles.module.css
index 75fee7dc1c..da6d72406f 100644
--- a/src/components/tx/security/redefine/styles.module.css
+++ b/src/components/tx/security/blockaid/styles.module.css
@@ -11,8 +11,9 @@
padding: 0;
}
-.wrapperBox :global .MuiAccordion-root.Mui-expanded {
- border-color: var(--color-border-light) !important;
+.wrapperBox :global .MuiAccordion-root.Mui-expanded,
+.wrapperBox :global .MuiAccordion-root {
+ border: none;
}
.wrapperBox {
@@ -98,3 +99,21 @@
position: absolute;
right: -58px;
}
+
+.resultAccordion :global .Mui-expanded.MuiAccordionSummary-root {
+ background: inherit;
+}
+
+.resultAccordion :global .Mui-expanded {
+ border: var(--color-border-light);
+}
+
+.customAlert {
+ border: none;
+}
+
+.riskConfirmationBlock {
+ background-color: var(--color-error-light);
+ border-bottom-left-radius: 6px;
+ border-bottom-right-radius: 6px;
+}
diff --git a/src/components/tx/security/blockaid/useBlockaid.ts b/src/components/tx/security/blockaid/useBlockaid.ts
new file mode 100644
index 0000000000..5ea657de25
--- /dev/null
+++ b/src/components/tx/security/blockaid/useBlockaid.ts
@@ -0,0 +1,58 @@
+import useAsync, { type AsyncResult } from '@/hooks/useAsync'
+import { useHasFeature } from '@/hooks/useChains'
+import useSafeInfo from '@/hooks/useSafeInfo'
+import useWallet from '@/hooks/wallets/useWallet'
+import { MODALS_EVENTS, trackEvent } from '@/services/analytics'
+import type { SecurityResponse } from '@/services/security/modules/types'
+import { FEATURES } from '@/utils/chains'
+import type { SafeTransaction } from '@safe-global/safe-core-sdk-types'
+import { useEffect, useMemo } from 'react'
+
+import type { EIP712TypedData } from '@safe-global/safe-gateway-typescript-sdk'
+import { BlockaidModule, type BlockaidModuleResponse } from '@/services/security/modules/BlockaidModule'
+
+const BlockaidModuleInstance = new BlockaidModule()
+
+const DEFAULT_ERROR_MESSAGE = 'Unavailable'
+
+export const useBlockaid = (
+ data: SafeTransaction | EIP712TypedData | undefined,
+): AsyncResult> => {
+ const { safe, safeAddress } = useSafeInfo()
+ const wallet = useWallet()
+ const isFeatureEnabled = useHasFeature(FEATURES.RISK_MITIGATION)
+
+ const [blockaidPayload, blockaidErrors, blockaidLoading] = useAsync>(
+ () => {
+ if (!isFeatureEnabled || !data || !wallet?.address) {
+ return
+ }
+
+ return BlockaidModuleInstance.scanTransaction({
+ chainId: Number(safe.chainId),
+ data,
+ safeAddress,
+ walletAddress: wallet.address,
+ threshold: safe.threshold,
+ })
+ },
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ [safe.chainId, safe.threshold, safeAddress, data, wallet?.address, isFeatureEnabled],
+ false,
+ )
+
+ const loading = blockaidLoading
+
+ useEffect(() => {
+ if (!loading && blockaidPayload) {
+ trackEvent({ ...MODALS_EVENTS.BLOCKAID_RESULT, label: blockaidPayload.severity })
+ }
+ }, [loading, blockaidPayload])
+
+ const errorMsg = useMemo(
+ () => (blockaidErrors ? new Error(DEFAULT_ERROR_MESSAGE) : blockaidPayload?.payload?.error),
+
+ [blockaidErrors, blockaidPayload],
+ )
+ return [blockaidPayload, errorMsg, loading]
+}
diff --git a/src/components/tx/security/redefine/RedefineHint.tsx b/src/components/tx/security/redefine/RedefineHint.tsx
deleted file mode 100644
index 8030ec9ec4..0000000000
--- a/src/components/tx/security/redefine/RedefineHint.tsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import { SecuritySeverity } from '@/services/security/modules/types'
-import { Alert, Box, List, ListItem, SvgIcon, Typography } from '@mui/material'
-import css from 'src/components/tx/security/redefine/styles.module.css'
-import AlertIcon from '@/public/images/notifications/alert.svg'
-import { mapRedefineSeverity } from '@/components/tx/security/redefine/useRedefine'
-
-export const RedefineHint = ({ severity, warnings }: { severity: SecuritySeverity; warnings: string[] }) => {
- const severityProps = mapRedefineSeverity[severity]
- const pluralizedLabel = (
- <>
- {warnings.length} {severityProps.label}
- {warnings.length > 1 ? 's' : ''}
- >
- )
-
- return (
- <>
- palette[severityProps.color].background }}
- icon={
- palette[severityProps.color].main,
- },
- }}
- />
- }
- >
- {severity !== SecuritySeverity.NONE && (
-
- {pluralizedLabel}
-
- )}
-
-
- {warnings.map((warning) => (
-
- {warning}
-
- ))}
-
-
-
- >
- )
-}
diff --git a/src/components/tx/security/redefine/index.tsx b/src/components/tx/security/redefine/index.tsx
deleted file mode 100644
index 99c6b410bf..0000000000
--- a/src/components/tx/security/redefine/index.tsx
+++ /dev/null
@@ -1,207 +0,0 @@
-import { useContext, useEffect, useRef } from 'react'
-import { mapRedefineSeverity } from '@/components/tx/security/redefine/useRedefine'
-import { TxSecurityContext } from '@/components/tx/security/shared/TxSecurityContext'
-import { SecuritySeverity } from '@/services/security/modules/types'
-import groupBy from 'lodash/groupBy'
-import { Alert, Box, Checkbox, FormControlLabel, Paper, SvgIcon, Tooltip, Typography } from '@mui/material'
-import ExternalLink from '@/components/common/ExternalLink'
-import { FEATURES } from '@/utils/chains'
-import { useHasFeature } from '@/hooks/useChains'
-import { ErrorBoundary } from '@sentry/react'
-import { REDEFINE_ARTICLE, REDEFINE_SIMULATION_URL } from '@/config/constants'
-import css from 'src/components/tx/security/redefine/styles.module.css'
-import sharedCss from '@/components/tx/security/shared/styles.module.css'
-import RedefineLogoDark from '@/public/images/transactions/redefine-dark-mode.png'
-import RedefineLogo from '@/public/images/transactions/redefine.png'
-import Track from '@/components/common/Track'
-import { MODALS_EVENTS } from '@/services/analytics'
-import { useDarkMode } from '@/hooks/useDarkMode'
-import CircularProgress from '@mui/material/CircularProgress'
-import { RedefineHint } from '@/components/tx/security/redefine/RedefineHint'
-import InfoIcon from '@/public/images/notifications/info.svg'
-import Image from 'next/image'
-import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider'
-
-const MAX_SHOWN_WARNINGS = 3
-
-const RedefineBlock = () => {
- const { severity, isLoading, error, needsRiskConfirmation, isRiskConfirmed, setIsRiskConfirmed, isRiskIgnored } =
- useContext(TxSecurityContext)
-
- const { safeTx } = useContext(SafeTxContext)
-
- // We either scan a tx or a message if tx is undefined
- const isTransaction = !!safeTx
- const checkboxRef = useRef(null)
-
- const isDarkMode = useDarkMode()
- const severityProps = severity !== undefined ? mapRedefineSeverity[severity] : undefined
-
- const toggleConfirmation = () => {
- setIsRiskConfirmed((prev) => !prev)
- }
-
- // Highlight checkbox if user tries to submit transaction without confirming risks
- useEffect(() => {
- if (isRiskIgnored) {
- checkboxRef.current?.scrollIntoView({ behavior: 'smooth', block: 'center' })
- }
- }, [isRiskIgnored, checkboxRef])
-
- if (!severityProps && !isLoading && !error) {
- return null
- }
-
- return (
-
-
-
-
- Scan for risks
-
- This {isTransaction ? 'transaction' : 'message'} has been automatically scanned for risks to help
- prevent scams.
-
- Learn more about security scans
-
- .
- >
- }
- arrow
- placement="top"
- >
-
-
-
-
-
-
-
- Powered by{' '}
-
-
-
-
-
-
-
- {isLoading ? (
- palette.text.secondary,
- }}
- />
- ) : severityProps ? (
-
-
- {severityProps.label}
-
- ) : error ? (
-
- {error.message}
-
- ) : null}
-
-
-
- {needsRiskConfirmation && (
-
-
- }
- className={isRiskIgnored ? css.checkboxError : ''}
- />
-
-
- )}
-
-
- )
-}
-
-export const Redefine = () => {
- const isFeatureEnabled = useHasFeature(FEATURES.RISK_MITIGATION)
-
- if (!isFeatureEnabled) {
- return null
- }
-
- return (
- Error showing scan result}>
-
-
- )
-}
-
-export const RedefineMessage = () => {
- const { severity, warnings, simulationUuid } = useContext(TxSecurityContext)
-
- /* Evaluate security warnings */
- const relevantWarnings = warnings.filter((warning) => warning.severity !== SecuritySeverity.NONE)
- const shownWarnings = relevantWarnings.slice(0, MAX_SHOWN_WARNINGS)
- const hiddenWarningCount = warnings.length - shownWarnings.length
- const hiddenMaxSeverity =
- hiddenWarningCount > 0 ? relevantWarnings[MAX_SHOWN_WARNINGS]?.severity : SecuritySeverity.NONE
-
- const groupedShownWarnings = groupBy(shownWarnings, (warning) => warning.severity)
- const sortedSeverities = Object.keys(groupedShownWarnings).sort((a, b) => (Number(a) < Number(b) ? 1 : -1))
-
- if (sortedSeverities.length === 0 && hiddenWarningCount === 0 && !simulationUuid) return null
-
- return (
-
- {sortedSeverities.map((key) => (
- warning.description.short)}
- />
- ))}
-
- {hiddenWarningCount > 0 && (
- 1 ? 's' : ''}`]}
- />
- )}
-
- {simulationUuid && (
-
- {severity === SecuritySeverity.NONE && (
-
- {mapRedefineSeverity[severity].label}
-
- )}
- For a comprehensive risk overview,{' '}
-
- see the full report on Redefine
-
-
- )}
-
- )
-}
diff --git a/src/components/tx/security/redefine/useRedefine.test.ts b/src/components/tx/security/redefine/useRedefine.test.ts
deleted file mode 100644
index e77f7cc919..0000000000
--- a/src/components/tx/security/redefine/useRedefine.test.ts
+++ /dev/null
@@ -1,330 +0,0 @@
-import { act, renderHook, waitFor } from '@/tests/test-utils'
-import { REDEFINE_RETRY_TIMEOUT, useRedefine } from './useRedefine'
-import * as useWallet from '@/hooks/wallets/useWallet'
-import * as useChains from '@/hooks/useChains'
-import type { ConnectedWallet } from '@/hooks/wallets/useOnboard'
-import { toBeHex } from 'ethers'
-import { type RedefineResponse, REDEFINE_ERROR_CODES } from '@/services/security/modules/RedefineModule'
-import { SecuritySeverity } from '@/services/security/modules/types'
-import { safeTxBuilder } from '@/tests/builders/safeTx'
-import { eip712TypedDataBuilder } from '@/tests/builders/messages'
-
-const setupFetchStub = (data: any) => (_url: string) => {
- return Promise.resolve({
- json: () => Promise.resolve(data),
- status: 200,
- ok: true,
- })
-}
-
-enum TEST_CASES {
- MESSAGE = 'EIP 712 Message',
- TRANSACTION = 'SafeTransaction',
-}
-
-// Mock REDEFINE_API
-jest.mock('@/config/constants', () => ({
- ...jest.requireActual('@/config/constants'),
- REDEFINE_API: 'https://redefine-api.test',
-}))
-
-describe.each([TEST_CASES.MESSAGE, TEST_CASES.TRANSACTION])('useRedefine for %s', (testCase) => {
- let mockUseWallet: jest.SpyInstance
-
- const mockPayload = testCase === TEST_CASES.TRANSACTION ? safeTxBuilder().build() : eip712TypedDataBuilder().build()
-
- beforeEach(() => {
- jest.resetAllMocks()
- jest.useFakeTimers()
- mockUseWallet = jest.spyOn(useWallet, 'default')
- mockUseWallet.mockImplementation(() => null)
-
- global.fetch = jest.fn()
- })
-
- it('should return undefined without data', async () => {
- const { result } = renderHook(() => useRedefine(undefined))
-
- await waitFor(() => {
- expect(result.current[0]).toBeUndefined()
- expect(result.current[1]).toBeUndefined()
- expect(result.current[2]).toBeFalsy()
- })
- })
-
- it('should return undefined without connected wallet', async () => {
- const { result } = renderHook(() => useRedefine(mockPayload))
-
- await waitFor(() => {
- expect(result.current[0]).toBeUndefined()
- expect(result.current[1]).toBeUndefined()
- expect(result.current[2]).toBeFalsy()
- })
- })
-
- it('should return undefined without feature enabled', async () => {
- const walletAddress = toBeHex('0x1', 20)
-
- mockUseWallet.mockImplementation(() => ({
- address: walletAddress,
- chainId: '1',
- label: 'Testwallet',
- provider: {} as any,
- }))
-
- jest.spyOn(useChains, 'useHasFeature').mockReturnValue(false)
-
- const { result } = renderHook(() => useRedefine(mockPayload))
-
- await waitFor(() => {
- expect(result.current[0]).toBeUndefined()
- expect(result.current[1]).toEqual(undefined)
- expect(result.current[2]).toBeFalsy()
- })
- })
-
- it('should handle request errors', async () => {
- const walletAddress = toBeHex('0x1', 20)
-
- mockUseWallet.mockImplementation(() => ({
- address: walletAddress,
- chainId: '1',
- label: 'Testwallet',
- provider: {} as any,
- }))
-
- jest.spyOn(useChains, 'useHasFeature').mockReturnValue(true)
-
- const mockFetch = jest.spyOn(global, 'fetch')
- mockFetch.mockImplementation(() => Promise.reject({ message: '403 not authorized' }))
-
- const { result } = renderHook(() => useRedefine(mockPayload))
-
- await waitFor(() => {
- expect(result.current[0]).toBeUndefined()
- expect(result.current[1]).toEqual(new Error('Unavailable'))
- expect(result.current[2]).toBeFalsy()
- })
- })
-
- it('should return the redefine issues', async () => {
- const walletAddress = toBeHex('0x1', 20)
-
- const mockRedefineResponse: RedefineResponse = {
- data: {
- insights: {
- verdict: {
- code: 1,
- label: 'LOW',
- },
- issues: [
- {
- category: 'SOME_FAKE_WARNING',
- description: {
- short: 'Test',
- long: 'Just a test',
- },
- severity: {
- code: 1,
- label: 'LOW',
- },
- },
- ],
- },
- simulation: {
- block: '123',
- time: '2023-01-01-23:00',
- uuid: '123-456-789',
- },
- balanceChange: {
- in: [
- {
- address: toBeHex('0x2', 20),
- amount: {
- normalizedValue: '0.1',
- value: '100000000000000000',
- },
- decimals: 18,
- name: 'Test',
- symbol: 'TST',
- type: 'ERC20',
- },
- ],
- out: [],
- },
- },
- errors: [],
- }
-
- mockUseWallet.mockImplementation(() => ({
- address: walletAddress,
- chainId: '1',
- label: 'Testwallet',
- provider: {} as any,
- }))
-
- jest.spyOn(useChains, 'useHasFeature').mockReturnValue(true)
-
- global.fetch = jest.fn().mockImplementation(setupFetchStub(mockRedefineResponse))
-
- const mockFetch = jest.spyOn(global, 'fetch')
- const { result } = renderHook(() => useRedefine(mockPayload))
-
- await waitFor(() => {
- expect(result.current[1]).toBeUndefined()
- expect(result.current[0]).toBeDefined()
- const response = result.current[0]
- expect(response?.severity).toEqual(SecuritySeverity.LOW)
- expect(response?.payload?.issues).toHaveLength(1)
- expect(response?.payload?.balanceChange?.in).toHaveLength(1)
- expect(result.current[2]).toBeFalsy()
- expect(mockFetch).toHaveBeenCalledTimes(1)
- })
-
- // Should not poll again without error 1000
- await act(() => {
- jest.advanceTimersByTime(REDEFINE_RETRY_TIMEOUT)
- })
-
- expect(mockFetch).toHaveBeenCalledTimes(1)
- })
-
- it('should poll again on error code 1000', async () => {
- const walletAddress = toBeHex('0x1', 20)
-
- const mockPartialRedefineResponse: RedefineResponse = {
- data: {
- insights: {
- verdict: {
- code: 1,
- label: 'LOW',
- },
- issues: [
- {
- category: 'SOME_FAKE_WARNING',
- description: {
- short: 'Test',
- long: 'Just a test',
- },
- severity: {
- code: 1,
- label: 'LOW',
- },
- },
- ],
- },
- simulation: {
- block: '123',
- time: '2023-01-01-23:00',
- uuid: '123-456-789',
- },
- },
- errors: [
- {
- code: REDEFINE_ERROR_CODES.ANALYSIS_IN_PROGRESS,
- message: 'Analysis still in progress.',
- },
- ],
- }
-
- const mockFullRedefineResponse: RedefineResponse = {
- data: {
- balanceChange: {
- in: [
- {
- address: toBeHex('0x2', 20),
- amount: {
- normalizedValue: '0.1',
- value: '100000000000000000',
- },
- decimals: 18,
- name: 'Test',
- symbol: 'TST',
- type: 'ERC20',
- },
- ],
- out: [],
- },
- simulation: {
- block: '123',
- time: '2023-01-01-23:00',
- uuid: '123-456-789',
- },
- insights: {
- verdict: {
- code: 1,
- label: 'LOW',
- },
- issues: [
- {
- category: 'SOME_FAKE_WARNING',
- description: {
- short: 'Test',
- long: 'Just a test',
- },
- severity: {
- code: 1,
- label: 'LOW',
- },
- },
- ],
- },
- },
- errors: [],
- }
-
- mockUseWallet.mockImplementation(() => ({
- address: walletAddress,
- chainId: '1',
- label: 'Testwallet',
- provider: {} as any,
- }))
-
- jest.spyOn(useChains, 'useHasFeature').mockReturnValue(true)
-
- global.fetch = jest.fn().mockImplementation(setupFetchStub(mockPartialRedefineResponse))
-
- let mockFetch = jest.spyOn(global, 'fetch')
- const { result } = renderHook(() => useRedefine(mockPayload))
-
- await waitFor(() => {
- expect(result.current[0]).toBeDefined()
- const response = result.current[0]
- expect(response?.severity).toEqual(SecuritySeverity.LOW)
- expect(response?.payload?.issues).toHaveLength(1)
- expect(response?.payload?.balanceChange).toBeUndefined()
- expect(result.current[1]).toBeUndefined()
- expect(result.current[2]).toBeTruthy()
-
- expect(mockFetch).toHaveBeenCalledTimes(1)
- })
-
- global.fetch = jest.fn().mockImplementation(setupFetchStub(mockFullRedefineResponse))
-
- mockFetch = jest.spyOn(global, 'fetch')
-
- // Should poll again on error 1000
- await act(() => {
- jest.advanceTimersByTime(REDEFINE_RETRY_TIMEOUT)
- })
-
- await waitFor(() => {
- expect(result.current[0]).toBeDefined()
- const response = result.current[0]
- expect(response?.severity).toEqual(SecuritySeverity.LOW)
- expect(response?.payload?.issues).toHaveLength(1)
- expect(response?.payload?.balanceChange?.in).toHaveLength(1)
- expect(result.current[1]).toBeUndefined()
- expect(result.current[2]).toBeFalsy()
-
- expect(mockFetch).toHaveBeenCalledTimes(1)
- })
-
- // Should not poll again after full result without error 1000
- // Should not poll again without error 1000
- await act(() => {
- jest.advanceTimersByTime(REDEFINE_RETRY_TIMEOUT)
- })
- expect(mockFetch).toHaveBeenCalledTimes(1)
- })
-})
diff --git a/src/components/tx/security/redefine/useRedefine.ts b/src/components/tx/security/redefine/useRedefine.ts
deleted file mode 100644
index d1f6d3b620..0000000000
--- a/src/components/tx/security/redefine/useRedefine.ts
+++ /dev/null
@@ -1,146 +0,0 @@
-import useAsync, { type AsyncResult } from '@/hooks/useAsync'
-import { useHasFeature } from '@/hooks/useChains'
-import useSafeInfo from '@/hooks/useSafeInfo'
-import useWallet from '@/hooks/wallets/useWallet'
-import { MODALS_EVENTS, trackEvent } from '@/services/analytics'
-import {
- RedefineModule,
- type RedefineModuleResponse,
- REDEFINE_ERROR_CODES,
-} from '@/services/security/modules/RedefineModule'
-import type { SecurityResponse } from '@/services/security/modules/types'
-import { FEATURES } from '@/utils/chains'
-import type { SafeTransaction } from '@safe-global/safe-core-sdk-types'
-import { useState, useEffect, useMemo, type ComponentType } from 'react'
-import { type AlertColor } from '@mui/material'
-import { SecuritySeverity } from '@/services/security/modules/types'
-import CloseIcon from '@/public/images/common/close.svg'
-import InfoIcon from '@/public/images/notifications/info.svg'
-import CheckIcon from '@/public/images/common/check.svg'
-import type { EIP712TypedData } from '@safe-global/safe-gateway-typescript-sdk'
-
-export const REDEFINE_RETRY_TIMEOUT = 2_000
-const RedefineModuleInstance = new RedefineModule()
-
-const DEFAULT_ERROR_MESSAGE = 'Unavailable'
-
-const CRITICAL_ERRORS: Record = {
- [1001]: 'Simulation failed',
- [2000]: DEFAULT_ERROR_MESSAGE,
- [3000]: DEFAULT_ERROR_MESSAGE,
-}
-
-type SecurityWarningProps = {
- color: AlertColor
- icon: ComponentType
- label: string
- action?: string
-}
-
-const ACTION_REJECT = 'Reject this transaction'
-const ACTION_REVIEW = 'Review before processing'
-
-export const mapRedefineSeverity: Record = {
- [SecuritySeverity.CRITICAL]: {
- action: ACTION_REJECT,
- color: 'error',
- icon: CloseIcon,
- label: 'critical risk',
- },
- [SecuritySeverity.HIGH]: {
- action: ACTION_REJECT,
- color: 'error',
- icon: CloseIcon,
- label: 'high risk',
- },
- [SecuritySeverity.MEDIUM]: {
- action: ACTION_REVIEW,
- color: 'warning',
- icon: InfoIcon,
- label: 'medium risk',
- },
- [SecuritySeverity.LOW]: {
- action: ACTION_REVIEW,
- color: 'warning',
- icon: InfoIcon,
- label: 'small risk',
- },
- [SecuritySeverity.NONE]: {
- color: 'success',
- icon: CheckIcon,
- label: 'No issues found',
- },
-}
-
-export const useRedefine = (
- data: SafeTransaction | EIP712TypedData | undefined,
-): AsyncResult> => {
- const { safe, safeAddress } = useSafeInfo()
- const wallet = useWallet()
- const [retryCounter, setRetryCounter] = useState(0)
- const isFeatureEnabled = useHasFeature(FEATURES.RISK_MITIGATION)
-
- // Memoized JSON data to avoid unnecessary requests
- const jsonData = useMemo(() => {
- if (!data) return ''
- let adjustedData = data
- if ('data' in data) {
- // We need to set nonce to 0 to avoid repeated requests with an updated nonce
- adjustedData = { ...data, data: { ...data.data, nonce: 0 } }
- }
- return JSON.stringify(adjustedData)
- }, [data])
-
- const [redefinePayload, redefineErrors, redefineLoading] = useAsync>(
- () => {
- if (!isFeatureEnabled || !jsonData || !wallet?.address) {
- return
- }
-
- return RedefineModuleInstance.scanTransaction({
- chainId: Number(safe.chainId),
- data: JSON.parse(jsonData),
- safeAddress,
- walletAddress: wallet.address,
- threshold: safe.threshold,
- })
- },
- // eslint-disable-next-line react-hooks/exhaustive-deps
- [safe.chainId, safe.threshold, safeAddress, jsonData, wallet?.address, retryCounter, isFeatureEnabled],
- false,
- )
-
- const isAnalyzing = !!redefinePayload?.payload?.errors.some(
- (error) => error.code === REDEFINE_ERROR_CODES.ANALYSIS_IN_PROGRESS,
- )
-
- const loading = redefineLoading || isAnalyzing
-
- const error = useMemo(() => {
- const simulationErrors =
- redefinePayload?.payload?.errors.filter((error) => CRITICAL_ERRORS[error.code] !== undefined) ?? []
- const errorMessage = redefineErrors
- ? DEFAULT_ERROR_MESSAGE
- : simulationErrors.length > 0
- ? CRITICAL_ERRORS[simulationErrors[0].code]
- : undefined
- return errorMessage ? new Error(errorMessage) : undefined
- }, [redefineErrors, redefinePayload?.payload?.errors])
-
- useEffect(() => {
- if (!isAnalyzing) {
- return
- }
-
- let timeoutId = setTimeout(() => setRetryCounter((prev) => prev + 1), REDEFINE_RETRY_TIMEOUT)
- return () => clearTimeout(timeoutId)
- }, [redefinePayload, isAnalyzing])
-
- useEffect(() => {
- if (!loading && !error && redefinePayload) {
- trackEvent({ ...MODALS_EVENTS.REDEFINE_RESULT, label: redefinePayload.severity })
- }
- }, [error, loading, redefinePayload])
-
- return [redefinePayload, error, loading]
-}
diff --git a/src/components/tx/security/shared/TxSecurityContext.tsx b/src/components/tx/security/shared/TxSecurityContext.tsx
index 62f267b83b..edcaa570ae 100644
--- a/src/components/tx/security/shared/TxSecurityContext.tsx
+++ b/src/components/tx/security/shared/TxSecurityContext.tsx
@@ -1,16 +1,20 @@
-import { type RedefineModuleResponse } from '@/services/security/modules/RedefineModule'
import { SecuritySeverity } from '@/services/security/modules/types'
import { SafeTxContext } from '@/components/tx-flow/SafeTxProvider'
import { createContext, type Dispatch, type SetStateAction, useContext, useMemo, useState } from 'react'
-import { useRedefine } from '../redefine/useRedefine'
+import type { BlockaidModuleResponse } from '@/services/security/modules/BlockaidModule'
+import { useBlockaid } from '../blockaid/useBlockaid'
export const defaultSecurityContextValues = {
- warnings: [],
- simulationUuid: undefined,
- balanceChange: undefined,
- severity: SecuritySeverity.NONE,
- isLoading: false,
- error: undefined,
+ blockaidResponse: {
+ warnings: [],
+ description: undefined,
+ classification: undefined,
+ reason: undefined,
+ balanceChange: undefined,
+ severity: SecuritySeverity.NONE,
+ isLoading: false,
+ error: undefined,
+ },
needsRiskConfirmation: false,
isRiskConfirmed: false,
setIsRiskConfirmed: () => {},
@@ -18,41 +22,54 @@ export const defaultSecurityContextValues = {
setIsRiskIgnored: () => {},
}
-export const TxSecurityContext = createContext<{
- warnings: NonNullable
- simulationUuid: string | undefined
- balanceChange: RedefineModuleResponse['balanceChange']
- severity: SecuritySeverity | undefined
- isLoading: boolean
- error: Error | undefined
+export type TxSecurityContextProps = {
+ blockaidResponse:
+ | {
+ description: BlockaidModuleResponse['description']
+ classification: BlockaidModuleResponse['classification']
+ reason: BlockaidModuleResponse['reason']
+ warnings: NonNullable
+ balanceChange: BlockaidModuleResponse['balanceChange'] | undefined
+ severity: SecuritySeverity | undefined
+ isLoading: boolean
+ error: Error | undefined
+ }
+ | undefined
needsRiskConfirmation: boolean
isRiskConfirmed: boolean
setIsRiskConfirmed: Dispatch>
isRiskIgnored: boolean
setIsRiskIgnored: Dispatch>
-}>(defaultSecurityContextValues)
+}
+
+export const TxSecurityContext = createContext(defaultSecurityContextValues)
export const TxSecurityProvider = ({ children }: { children: JSX.Element }) => {
const { safeTx, safeMessage } = useContext(SafeTxContext)
- const [redefineResponse, redefineError, redefineLoading] = useRedefine(safeTx ?? safeMessage)
+ const [blockaidResponse, blockaidError, blockaidLoading] = useBlockaid(safeTx ?? safeMessage)
+
const [isRiskConfirmed, setIsRiskConfirmed] = useState(false)
const [isRiskIgnored, setIsRiskIgnored] = useState(false)
const providedValue = useMemo(
() => ({
- severity: redefineResponse?.severity,
- simulationUuid: redefineResponse?.payload?.simulation?.uuid,
- warnings: redefineResponse?.payload?.issues || [],
- balanceChange: redefineResponse?.payload?.balanceChange,
- error: redefineError,
- isLoading: redefineLoading,
- needsRiskConfirmation: !!redefineResponse && redefineResponse.severity >= SecuritySeverity.HIGH,
+ blockaidResponse: {
+ description: blockaidResponse?.payload?.description,
+ reason: blockaidResponse?.payload?.reason,
+ classification: blockaidResponse?.payload?.classification,
+ severity: blockaidResponse?.severity,
+ warnings: blockaidResponse?.payload?.issues || [],
+ balanceChange: blockaidResponse?.payload?.balanceChange,
+ error: blockaidError,
+ isLoading: blockaidLoading,
+ },
+ needsRiskConfirmation: !!blockaidResponse && blockaidResponse.severity >= SecuritySeverity.HIGH,
isRiskConfirmed,
setIsRiskConfirmed,
isRiskIgnored: isRiskIgnored && !isRiskConfirmed,
setIsRiskIgnored,
}),
- [isRiskConfirmed, isRiskIgnored, redefineError, redefineLoading, redefineResponse],
+ [blockaidError, blockaidLoading, blockaidResponse, isRiskConfirmed, isRiskIgnored],
)
return {children}
diff --git a/src/components/tx/security/utils.ts b/src/components/tx/security/utils.ts
new file mode 100644
index 0000000000..cf4b91fa88
--- /dev/null
+++ b/src/components/tx/security/utils.ts
@@ -0,0 +1,47 @@
+import { SecuritySeverity } from '@/services/security/modules/types'
+import CloseIcon from '@/public/images/common/close.svg'
+import InfoIcon from '@/public/images/notifications/info.svg'
+import type { ComponentType } from 'react'
+import type { AlertColor } from '@mui/material'
+
+const ACTION_REJECT = 'Reject this transaction'
+const ACTION_REVIEW = 'Review before processing'
+
+export type SecurityWarningProps = {
+ color: AlertColor
+ icon: ComponentType
+ label: string
+ action?: string
+}
+
+export const mapSecuritySeverity: Record = {
+ [SecuritySeverity.CRITICAL]: {
+ action: ACTION_REJECT,
+ color: 'error',
+ icon: CloseIcon,
+ label: 'critical risk',
+ },
+ [SecuritySeverity.HIGH]: {
+ action: ACTION_REJECT,
+ color: 'error',
+ icon: CloseIcon,
+ label: 'high risk',
+ },
+ [SecuritySeverity.MEDIUM]: {
+ action: ACTION_REVIEW,
+ color: 'warning',
+ icon: InfoIcon,
+ label: 'warning',
+ },
+ [SecuritySeverity.LOW]: {
+ action: ACTION_REVIEW,
+ color: 'warning',
+ icon: InfoIcon,
+ label: 'warning',
+ },
+ [SecuritySeverity.NONE]: {
+ color: 'info',
+ icon: InfoIcon,
+ label: 'info',
+ },
+}
diff --git a/src/config/constants.ts b/src/config/constants.ts
index b8a20080f1..7f332d0ec7 100644
--- a/src/config/constants.ts
+++ b/src/config/constants.ts
@@ -101,9 +101,9 @@ export const TWITTER_URL = 'https://twitter.com/safe'
// Legal
export const IS_OFFICIAL_HOST = process.env.NEXT_PUBLIC_IS_OFFICIAL_HOST === 'true'
-// Risk mitigation (Redefine)
-export const REDEFINE_SIMULATION_URL = 'https://dashboard.redefine.net/reports/'
-export const REDEFINE_API = process.env.NEXT_PUBLIC_REDEFINE_API
+// Risk mitigation (Blockaid)
+export const BLOCKAID_API = 'https://client.blockaid.io'
+export const BLOCKAID_CLIENT_ID = process.env.NEXT_PUBLIC_BLOCKAID_CLIENT_ID
export const REDEFINE_ARTICLE = 'https://safe.mirror.xyz/rInLWZwD_sf7enjoFerj6FIzCYmVMGrrV8Nhg4THdwI'
export const CHAINALYSIS_OFAC_CONTRACT = '0x40c57923924b5c5c5455c48d93317139addac8fb'
diff --git a/src/services/analytics/events/modals.ts b/src/services/analytics/events/modals.ts
index e90fb9d334..cba11054ec 100644
--- a/src/services/analytics/events/modals.ts
+++ b/src/services/analytics/events/modals.ts
@@ -53,6 +53,11 @@ export const MODALS_EVENTS = {
category: MODALS_CATEGORY,
event: EventType.META,
},
+ BLOCKAID_RESULT: {
+ action: 'Blockaid scan result',
+ category: MODALS_CATEGORY,
+ event: EventType.META,
+ },
OPEN_SPEED_UP_MODAL: {
action: 'Open speed-up modal',
category: MODALS_CATEGORY,
diff --git a/src/services/security/modules/BlockaidModule/index.ts b/src/services/security/modules/BlockaidModule/index.ts
new file mode 100644
index 0000000000..0f85c195c1
--- /dev/null
+++ b/src/services/security/modules/BlockaidModule/index.ts
@@ -0,0 +1,165 @@
+import { isEIP712TypedData } from '@/utils/safe-messages'
+import { normalizeTypedData } from '@/utils/web3'
+import { type SafeTransaction } from '@safe-global/safe-core-sdk-types'
+import { generateTypedData } from '@safe-global/protocol-kit/dist/src/utils/eip-712'
+import type { EIP712TypedData } from '@safe-global/safe-gateway-typescript-sdk'
+import { type SecurityResponse, type SecurityModule, SecuritySeverity } from '../types'
+import type { AssetDiff, TransactionScanResponse } from './types'
+import { BLOCKAID_API, BLOCKAID_CLIENT_ID } from '@/config/constants'
+
+/** @see https://docs.blockaid.io/docs/supported-chains */
+const API_CHAINS: Record = {
+ 1: 'ethereum',
+ 10: 'optimism',
+ 56: 'bsc',
+ 100: 'gnosis',
+ 137: 'polygon',
+ 238: 'blast',
+ 324: 'zksync',
+ 8453: 'base',
+ 42161: 'arbitrum',
+ 43114: 'avalanche',
+ 59144: 'linea',
+ 534352: 'scroll',
+ 7777777: 'zora',
+}
+const blockaidSeverityMap: Record = {
+ Malicious: SecuritySeverity.HIGH,
+ Warning: SecuritySeverity.MEDIUM,
+ Benign: SecuritySeverity.NONE,
+ Info: SecuritySeverity.NONE,
+}
+
+export type BlockaidModuleRequest = {
+ chainId: number
+ safeAddress: string
+ walletAddress: string
+ data: SafeTransaction | EIP712TypedData
+ threshold: number
+}
+
+export type BlockaidModuleResponse = {
+ description?: string
+ classification?: string
+ reason?: string
+ issues: {
+ severity: SecuritySeverity
+ description: string
+ }[]
+ balanceChange: AssetDiff[]
+ error: Error | undefined
+}
+
+type BlockaidPayload = {
+ chain: string
+ account_address: string
+ metadata: {
+ domain: string
+ }
+ data: {
+ method: 'eth_signTypedData_v4'
+ params: [string, string]
+ }
+ options: ['simulation', 'validation']
+}
+
+export class BlockaidModule implements SecurityModule {
+ static prepareMessage(request: BlockaidModuleRequest): string {
+ const { data, safeAddress, chainId } = request
+ if (isEIP712TypedData(data)) {
+ const normalizedMsg = normalizeTypedData(data)
+ return JSON.stringify(normalizedMsg)
+ } else {
+ return JSON.stringify(
+ generateTypedData({
+ safeAddress,
+ safeVersion: '1.3.0', // TODO: pass to module, taking into account that lower Safe versions don't have chainId in payload
+ chainId: BigInt(chainId),
+ data: {
+ ...data.data,
+ safeTxGas: data.data.safeTxGas,
+ baseGas: data.data.baseGas,
+ gasPrice: data.data.gasPrice,
+ },
+ }),
+ )
+ }
+ }
+ async scanTransaction(request: BlockaidModuleRequest): Promise> {
+ if (!BLOCKAID_CLIENT_ID) {
+ throw new Error('Security check CLIENT_ID not configured')
+ }
+
+ const { chainId, safeAddress, data } = request
+
+ if (!API_CHAINS[chainId]) {
+ throw new Error('Security checks are not available on the current chain.')
+ }
+
+ const message = BlockaidModule.prepareMessage(request)
+
+ const payload: BlockaidPayload = {
+ chain: API_CHAINS[chainId],
+ account_address: safeAddress,
+ data: {
+ method: 'eth_signTypedData_v4',
+ params: [safeAddress, message],
+ },
+ options: ['simulation', 'validation'],
+ metadata: {
+ // TODO: Pass domain from safe app or wallet connect connection if the tx originates from there
+ domain: window.location.host,
+ },
+ }
+ const res = await fetch(`${BLOCKAID_API}/v0/evm/json-rpc/scan`, {
+ method: 'POST',
+ headers: {
+ 'content-type': 'application/json',
+ accept: 'application/json',
+ 'X-CLIENT-ID': BLOCKAID_CLIENT_ID,
+ },
+ body: JSON.stringify(payload),
+ })
+
+ if (!res.ok) {
+ throw new Error('Blockaid scan failed', await res.json())
+ }
+
+ const result = (await res.json()) as TransactionScanResponse
+
+ const issues = (result.validation?.features ?? [])
+ .filter((feature) => feature.type === 'Malicious' || feature.type === 'Warning')
+ .map((feature) => ({
+ severity: blockaidSeverityMap[feature.type],
+ description: feature.description,
+ }))
+
+ const simulation = result.simulation
+ let balanceChange: AssetDiff[] = []
+ let error: Error | undefined = undefined
+ if (simulation?.status === 'Success') {
+ balanceChange = simulation.assets_diffs[safeAddress]
+ } else if (simulation?.status === 'Error') {
+ error = new Error('Simulation failed')
+ }
+
+ // Sometimes the validation is missing
+ if (result.validation === undefined) {
+ error = new Error('Validation result missing')
+ }
+
+ return {
+ severity: result.validation?.result_type
+ ? blockaidSeverityMap[result.validation.result_type]
+ : SecuritySeverity.NONE ?? SecuritySeverity.NONE,
+ payload: {
+ description: result.validation?.description,
+ classification: result.validation?.classification,
+ reason: result.validation?.reason,
+ issues,
+ balanceChange,
+ error,
+ },
+ }
+ }
+}
diff --git a/src/services/security/modules/BlockaidModule/types.ts b/src/services/security/modules/BlockaidModule/types.ts
new file mode 100644
index 0000000000..e956e32f87
--- /dev/null
+++ b/src/services/security/modules/BlockaidModule/types.ts
@@ -0,0 +1,619 @@
+export interface AddressAssetExposure {
+ /**
+ * description of the asset for the current diff
+ */
+ asset: Erc20TokenDetails | Erc1155TokenDetails | Erc721TokenDetails | NonercTokenDetails
+
+ /**
+ * dictionary of spender addresses where the exposure has changed during this
+ * transaction for the current address and asset
+ */
+ spenders: Record
+}
+
+export interface AssetDiff {
+ /**
+ * description of the asset for the current diff
+ */
+ asset: Erc20TokenDetails | Erc1155TokenDetails | Erc721TokenDetails | NonercTokenDetails | NativeAssetDetails
+
+ /**
+ * amount of the asset that was transferred to the address in this transaction
+ */
+ in: Array
+
+ /**
+ * amount of the asset that was transferred from the address in this transaction
+ */
+ out: Array
+}
+
+export type GeneralAssetDiff = Erc1155Diff | Erc721Diff | Erc20Diff | NativeDiff
+
+export interface Erc1155Diff {
+ /**
+ * id of the token
+ */
+ token_id: number
+
+ /**
+ * value before divided by decimal, that was transferred from this address
+ */
+ value: string
+
+ /**
+ * url of the token logo
+ */
+ logo_url?: string
+
+ /**
+ * user friendly description of the asset transfer
+ */
+ summary?: string
+
+ /**
+ * usd equal of the asset that was transferred from this address
+ */
+ usd_price?: string
+}
+
+export interface Erc1155Exposure {
+ exposure: Array
+
+ /**
+ * boolean indicates whether an is_approved_for_all function was used (missing in
+ * case of ERC20 / ERC1155)
+ */
+ is_approved_for_all: boolean
+
+ /**
+ * user friendly description of the approval
+ */
+ summary?: string
+}
+
+export interface Erc1155TokenDetails {
+ /**
+ * address of the token
+ */
+ address: string
+
+ /**
+ * asset type.
+ */
+ type: 'ERC1155'
+
+ /**
+ * url of the token logo
+ */
+ logo_url?: string
+
+ /**
+ * string represents the name of the asset
+ */
+ name?: string
+
+ /**
+ * asset's symbol name
+ */
+ symbol?: string
+}
+
+export interface Erc20Diff {
+ /**
+ * value before divided by decimal, that was transferred from this address
+ */
+ raw_value: string
+
+ /**
+ * user friendly description of the asset transfer
+ */
+ summary?: string
+
+ /**
+ * usd equal of the asset that was transferred from this address
+ */
+ usd_price?: string
+
+ /**
+ * value after divided by decimals, that was transferred from this address
+ */
+ value?: string
+}
+
+export interface Erc20Exposure {
+ /**
+ * the amount that was asked in the approval request for this spender from the
+ * current address and asset
+ */
+ approval: number
+
+ exposure: Array
+
+ /**
+ * the expiration time of the permit2 protocol
+ */
+ expiration?: string
+
+ /**
+ * user friendly description of the approval
+ */
+ summary?: string
+}
+
+export interface Erc20TokenDetails {
+ /**
+ * address of the token
+ */
+ address: string
+
+ /**
+ * asset's decimals
+ */
+ decimals: number
+
+ /**
+ * asset type.
+ */
+ type: 'ERC20'
+
+ /**
+ * url of the token logo
+ */
+ logo_url?: string
+
+ /**
+ * string represents the name of the asset
+ */
+ name?: string
+
+ /**
+ * asset's symbol name
+ */
+ symbol?: string
+}
+
+export interface Erc721Diff {
+ /**
+ * id of the token
+ */
+ token_id: number
+
+ /**
+ * url of the token logo
+ */
+ logo_url?: string
+
+ /**
+ * user friendly description of the asset transfer
+ */
+ summary?: string
+
+ /**
+ * usd equal of the asset that was transferred from this address
+ */
+ usd_price?: string
+}
+
+export interface Erc721Exposure {
+ exposure: Array
+
+ /**
+ * boolean indicates whether an is_approved_for_all function was used (missing in
+ * case of ERC20 / ERC1155)
+ */
+ is_approved_for_all: boolean
+
+ /**
+ * user friendly description of the approval
+ */
+ summary?: string
+}
+
+export interface Erc721TokenDetails {
+ /**
+ * address of the token
+ */
+ address: string
+
+ /**
+ * asset type.
+ */
+ type: 'ERC721'
+
+ /**
+ * url of the token logo
+ */
+ logo_url?: string
+
+ /**
+ * string represents the name of the asset
+ */
+ name?: string
+
+ /**
+ * asset's symbol name
+ */
+ symbol?: string
+}
+
+export interface Metadata {
+ /**
+ * cross reference transaction against the domain.
+ */
+ domain: string
+}
+
+export interface NativeAssetDetails {
+ chain_id: number
+
+ chain_name: string
+
+ decimals: number
+
+ logo_url: string
+
+ /**
+ * asset type.
+ */
+ type: 'NATIVE'
+
+ /**
+ * string represents the name of the asset
+ */
+ name?: string
+
+ /**
+ * asset's symbol name
+ */
+ symbol?: string
+}
+
+export interface NativeDiff {
+ /**
+ * value before divided by decimal, that was transferred from this address
+ */
+ raw_value: string
+
+ /**
+ * user friendly description of the asset transfer
+ */
+ summary?: string
+
+ /**
+ * usd equal of the asset that was transferred from this address
+ */
+ usd_price?: string
+
+ /**
+ * value after divided by decimals, that was transferred from this address
+ */
+ value?: string
+}
+
+export interface NonercTokenDetails {
+ /**
+ * address of the token
+ */
+ address: string
+
+ /**
+ * asset type.
+ */
+ type: 'NONERC'
+
+ /**
+ * url of the token logo
+ */
+ logo_url?: string
+
+ /**
+ * string represents the name of the asset
+ */
+ name?: string
+
+ /**
+ * asset's symbol name
+ */
+ symbol?: string
+}
+
+export type TransactionSimulationResponse = TransactionSimulation | TransactionSimulationError
+
+export type TransactionValidationResponse = TransactionValidation | TransactionValidationError
+
+/**
+ * The chain name
+ */
+export type TokenScanSupportedChain =
+ | 'arbitrum'
+ | 'avalanche'
+ | 'base'
+ | 'bsc'
+ | 'ethereum'
+ | 'optimism'
+ | 'polygon'
+ | 'zora'
+ | 'solana'
+ | 'unknown'
+
+export interface TransactionScanFeature {
+ /**
+ * Textual description
+ */
+ description: string
+
+ /**
+ * Feature name
+ */
+ feature_id: string
+
+ /**
+ * An enumeration.
+ */
+ type: 'Malicious' | 'Warning' | 'Benign' | 'Info'
+
+ /**
+ * Address the feature refers to
+ */
+ address?: string
+}
+
+export interface TransactionScanResponse {
+ block: string
+
+ chain: string
+
+ events?: Array
+
+ features?: unknown
+
+ gas_estimation?:
+ | TransactionScanResponse.TransactionScanGasEstimation
+ | TransactionScanResponse.TransactionScanGasEstimationError
+
+ simulation?: TransactionSimulationResponse
+
+ validation?: TransactionValidationResponse
+}
+
+export namespace TransactionScanResponse {
+ export interface Event {
+ data: string
+
+ emitter_address: string
+
+ topics: Array
+
+ emitter_name?: string
+
+ name?: string
+
+ params?: Array
+ }
+
+ export namespace Event {
+ export interface Param {
+ type: string
+
+ value: string | unknown | Array
+
+ internalType?: string
+
+ name?: string
+ }
+ }
+
+ export interface TransactionScanGasEstimation {
+ estimate: number
+
+ status: 'Success'
+
+ used: number
+ }
+
+ export interface TransactionScanGasEstimationError {
+ error: string
+
+ status: 'Error'
+ }
+}
+
+/**
+ * The chain name
+ */
+export type TransactionScanSupportedChain =
+ | 'arbitrum'
+ | 'avalanche'
+ | 'base'
+ | 'base-sepolia'
+ | 'bsc'
+ | 'ethereum'
+ | 'optimism'
+ | 'polygon'
+ | 'zksync'
+ | 'zora'
+ | 'linea'
+ | 'blast'
+ | 'unknown'
+
+export interface TransactionSimulation {
+ /**
+ * Account summary for the account address. account address is determined implicit
+ * by the `from` field in the transaction request, or explicit by the
+ * account_address field in the request.
+ */
+ account_summary: TransactionSimulation.AccountSummary
+
+ /**
+ * a dictionary including additional information about each relevant address in the
+ * transaction.
+ */
+ address_details: Record
+
+ /**
+ * dictionary describes the assets differences as a result of this transaction for
+ * every involved address
+ */
+ assets_diffs: Record>
+
+ /**
+ * dictionary describes the exposure differences as a result of this transaction
+ * for every involved address (as a result of any approval / setApproval / permit
+ * function)
+ */
+ exposures: Record>
+
+ /**
+ * A string indicating if the simulation was successful or not.
+ */
+ status: 'Success'
+
+ /**
+ * dictionary represents the usd value each address gained / lost during this
+ * transaction
+ */
+ total_usd_diff: Record
+
+ /**
+ * a dictionary representing the usd value each address is exposed to, split by
+ * spenders
+ */
+ total_usd_exposure: Record>
+}
+
+export namespace TransactionSimulation {
+ /**
+ * Account summary for the account address. account address is determined implicit
+ * by the `from` field in the transaction request, or explicit by the
+ * account_address field in the request.
+ */
+ export interface AccountSummary {
+ /**
+ * All assets diffs related to the account address
+ */
+ assets_diffs: Array
+
+ /**
+ * All assets exposures related to the account address
+ */
+ exposures: Array
+
+ /**
+ * Total usd diff related to the account address
+ */
+ total_usd_diff: UsdDiff
+
+ /**
+ * Total usd exposure related to the account address
+ */
+ total_usd_exposure: Record
+ }
+
+ export interface AddressDetails {
+ /**
+ * contains the contract's name if the address is a verified contract
+ */
+ contract_name?: string
+
+ /**
+ * known name tag for the address
+ */
+ name_tag?: string
+ }
+}
+
+export interface TransactionSimulationError {
+ /**
+ * An error message if the simulation failed.
+ */
+ error: string
+
+ /**
+ * A string indicating if the simulation was successful or not.
+ */
+ status: 'Error'
+}
+
+export interface TransactionValidation {
+ /**
+ * A list of features about this transaction explaining the validation.
+ */
+ features: Array
+
+ /**
+ * An enumeration.
+ */
+ result_type: 'Benign' | 'Warning' | 'Malicious'
+
+ /**
+ * A string indicating if the simulation was successful or not.
+ */
+ status: 'Success'
+
+ /**
+ * A textual classification that can be presented to the user explaining the
+ * reason.
+ */
+ classification?: string
+
+ /**
+ * A textual description that can be presented to the user about what this
+ * transaction is doing.
+ */
+ description?: string
+
+ /**
+ * A textual description about the reasons the transaction was flagged with
+ * result_type.
+ */
+ reason?: string
+}
+
+export interface TransactionValidationError {
+ /**
+ * A textual classification that can be presented to the user explaining the
+ * reason.
+ */
+ classification: ''
+
+ /**
+ * A textual description that can be presented to the user about what this
+ * transaction is doing.
+ */
+ description: ''
+
+ /**
+ * An error message if the validation failed.
+ */
+ error: string
+
+ /**
+ * A list of features about this transaction explaining the validation.
+ */
+ features: Array
+
+ /**
+ * A textual description about the reasons the transaction was flagged with
+ * result_type.
+ */
+ reason: ''
+
+ /**
+ * A string indicating if the transaction is safe to sign or not.
+ */
+ result_type: 'Error'
+
+ /**
+ * A string indicating if the simulation was successful or not.
+ */
+ status: 'Success'
+}
+
+export interface UsdDiff {
+ in: string
+
+ out: string
+
+ total: string
+}
diff --git a/src/services/security/modules/RedefineModule/index.ts b/src/services/security/modules/RedefineModule/index.ts
deleted file mode 100644
index b0d7ac93ed..0000000000
--- a/src/services/security/modules/RedefineModule/index.ts
+++ /dev/null
@@ -1,178 +0,0 @@
-import { REDEFINE_API } from '@/config/constants'
-import { isEIP712TypedData } from '@/utils/safe-messages'
-import { normalizeTypedData } from '@/utils/web3'
-import { type SafeTransaction } from '@safe-global/safe-core-sdk-types'
-import { generateTypedData } from '@safe-global/protocol-kit/dist/src/utils/eip-712'
-import type { EIP712TypedData } from '@safe-global/safe-gateway-typescript-sdk'
-import { type SecurityResponse, type SecurityModule, SecuritySeverity } from '../types'
-
-export const enum REDEFINE_ERROR_CODES {
- ANALYSIS_IN_PROGRESS = 1000,
- SIMULATION_FAILED = 1001,
- INPUT_VALIDATION = 2000,
- BAD_REQUEST = 3000,
-}
-
-const redefineSeverityMap: Record = {
- CRITICAL: SecuritySeverity.CRITICAL,
- HIGH: SecuritySeverity.HIGH,
- MEDIUM: SecuritySeverity.MEDIUM,
- LOW: SecuritySeverity.LOW,
- NO_ISSUES: SecuritySeverity.NONE,
-}
-
-export type RedefineModuleRequest = {
- chainId: number
- safeAddress: string
- walletAddress: string
- data: SafeTransaction | EIP712TypedData
- threshold: number
-}
-
-export type RedefineModuleResponse = {
- issues?: Array<
- Omit['insights']['issues'][number], 'severity'> & {
- severity: SecuritySeverity
- }
- >
- balanceChange?: NonNullable['balanceChange']
- simulation?: NonNullable['simulation']
- errors: RedefineResponse['errors']
-}
-
-type RedefinePayload = {
- chainId: number
- domain?: string
- payload: {
- method: 'eth_signTypedData_v4'
- params: [string, string]
- }
-}
-
-type RedefineSeverity = {
- code: number
- label: 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW' | 'NO_ISSUES'
-}
-
-type RedefineBalanceChange =
- | {
- address: string
- amount: {
- value: string
- normalizedValue: string
- }
- type: 'ERC20'
- symbol: string
- decimals: number
- name: string
- }
- | {
- amount: {
- value: string
- normalizedValue: string
- }
- type: 'NATIVE'
- symbol: string
- decimals: number
- name: string
- }
- | { type: 'ERC721'; address: string; tokenId: string; name?: string; symbol?: string }
-
-export type RedefineResponse = {
- data?: {
- balanceChange?: {
- in: RedefineBalanceChange[]
- out: RedefineBalanceChange[]
- }
- insights: {
- issues: {
- description: {
- short: string
- long: string
- }
- severity: RedefineSeverity
- category: string
- }[]
- verdict: RedefineSeverity
- }
- simulation: {
- uuid: string
- time: string
- block: string
- }
- }
- errors: {
- code: number
- message: string
- extendedInfo?: Record
- }[]
-}
-
-export class RedefineModule implements SecurityModule {
- static prepareMessage(request: RedefineModuleRequest): string {
- const { data, safeAddress, chainId } = request
- if (isEIP712TypedData(data)) {
- const normalizedMsg = normalizeTypedData(data)
- return JSON.stringify(normalizedMsg)
- } else {
- return JSON.stringify(
- generateTypedData({
- safeAddress,
- safeVersion: '1.3.0', // TODO: pass to module, taking into account that lower Safe versions don't have chainId in payload
- chainId: BigInt(chainId),
- // TODO: find out why these types are incompaitble
- data: {
- ...data.data,
- safeTxGas: data.data.safeTxGas,
- baseGas: data.data.baseGas,
- gasPrice: data.data.gasPrice,
- },
- }),
- )
- }
- }
- async scanTransaction(request: RedefineModuleRequest): Promise> {
- if (!REDEFINE_API) {
- throw new Error('Redefine API URL is not set')
- }
-
- const { chainId, safeAddress, data } = request
-
- const message = RedefineModule.prepareMessage(request)
-
- const payload: RedefinePayload = {
- chainId,
- payload: {
- method: 'eth_signTypedData_v4',
- params: [safeAddress, message],
- },
- }
-
- const res = await fetch(REDEFINE_API, {
- method: 'POST',
- headers: {
- 'content-type': 'application/JSON',
- },
- body: JSON.stringify(payload),
- })
-
- if (!res.ok) {
- throw new Error('Redefine scan failed', await res.json())
- }
-
- const result = (await res.json()) as RedefineResponse
-
- return {
- severity: result.data ? redefineSeverityMap[result.data.insights.verdict.label] : SecuritySeverity.NONE,
- payload: {
- issues: result.data?.insights.issues.map((issue) => ({
- ...issue,
- severity: redefineSeverityMap[issue.severity.label],
- })),
- balanceChange: result.data?.balanceChange,
- simulation: isEIP712TypedData(data) ? undefined : result.data?.simulation,
- errors: result.errors,
- },
- }
- }
-}
From 221973d98d027c79e30e5e242cb516b5fa523722 Mon Sep 17 00:00:00 2001
From: Pooya Raki
Date: Thu, 12 Sep 2024 11:52:43 +0200
Subject: [PATCH 62/81] Refactor: replace deprecated timezone_offset parameter
with timezone (#4159)
* add timezone parameter to the transaction history endpoint, removes deprecated timezone_offset
* bump safe-gateway-typescript-sdk version
* Update package.json
---------
Co-authored-by: katspaugh <381895+katspaugh@users.noreply.github.com>
---
cypress/e2e/prodhealthcheck/tx_history.cy.js | 2 +-
cypress/e2e/prodhealthcheck/tx_history_2.cy.js | 2 +-
cypress/e2e/regression/tx_history.cy.js | 2 +-
cypress/e2e/regression/tx_history_2.cy.js | 2 +-
cypress/support/utils/txquery.js | 2 +-
package.json | 2 +-
src/services/transactions/index.tests.ts | 11 ++++++-----
src/services/transactions/index.ts | 4 ++--
src/utils/__tests__/tx-history-filter.test.ts | 7 ++++---
src/utils/tx-history-filter.ts | 4 ++--
yarn.lock | 8 ++++----
11 files changed, 24 insertions(+), 22 deletions(-)
diff --git a/cypress/e2e/prodhealthcheck/tx_history.cy.js b/cypress/e2e/prodhealthcheck/tx_history.cy.js
index 77482c11f7..8cd2dcfbd5 100644
--- a/cypress/e2e/prodhealthcheck/tx_history.cy.js
+++ b/cypress/e2e/prodhealthcheck/tx_history.cy.js
@@ -27,7 +27,7 @@ describe('Tx history tests 1', () => {
constants.stagingCGWSafes
}${staticSafes.SEP_STATIC_SAFE_7.substring(4)}/transactions/history**`,
(req) => {
- req.url = `https://safe-client.safe.global/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone_offset=7200000&trusted=false&cursor=limit=100&offset=1`
+ req.url = `https://safe-client.safe.global/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone=Europe/Berlin&trusted=false&cursor=limit=100&offset=1`
req.continue()
},
).as('allTransactions')
diff --git a/cypress/e2e/prodhealthcheck/tx_history_2.cy.js b/cypress/e2e/prodhealthcheck/tx_history_2.cy.js
index aa7bd17692..faa6f50bf0 100644
--- a/cypress/e2e/prodhealthcheck/tx_history_2.cy.js
+++ b/cypress/e2e/prodhealthcheck/tx_history_2.cy.js
@@ -30,7 +30,7 @@ describe('Tx history tests 2', () => {
constants.stagingCGWSafes
}${staticSafes.SEP_STATIC_SAFE_7.substring(4)}/transactions/history**`,
(req) => {
- req.url = `https://safe-client.safe.global/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone_offset=7200000&trusted=false&cursor=limit=100&offset=1`
+ req.url = `https://safe-client.safe.global/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone=Europe/Berlin&trusted=false&cursor=limit=100&offset=1`
req.continue()
},
).as('allTransactions')
diff --git a/cypress/e2e/regression/tx_history.cy.js b/cypress/e2e/regression/tx_history.cy.js
index eb154b0d6a..d528a9a925 100644
--- a/cypress/e2e/regression/tx_history.cy.js
+++ b/cypress/e2e/regression/tx_history.cy.js
@@ -27,7 +27,7 @@ describe('Tx history tests 1', () => {
constants.stagingCGWSafes
}${staticSafes.SEP_STATIC_SAFE_7.substring(4)}/transactions/history**`,
(req) => {
- req.url = `https://safe-client.staging.5afe.dev/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone_offset=7200000&trusted=false&cursor=limit=100&offset=1`
+ req.url = `https://safe-client.staging.5afe.dev/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone=Europe/Berlin&trusted=false&cursor=limit=100&offset=1`
req.continue()
},
).as('allTransactions')
diff --git a/cypress/e2e/regression/tx_history_2.cy.js b/cypress/e2e/regression/tx_history_2.cy.js
index 409250449f..4d36ce8c02 100644
--- a/cypress/e2e/regression/tx_history_2.cy.js
+++ b/cypress/e2e/regression/tx_history_2.cy.js
@@ -30,7 +30,7 @@ describe('Tx history tests 2', () => {
constants.stagingCGWSafes
}${staticSafes.SEP_STATIC_SAFE_7.substring(4)}/transactions/history**`,
(req) => {
- req.url = `https://safe-client.staging.5afe.dev/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone_offset=7200000&trusted=false&cursor=limit=100&offset=1`
+ req.url = `https://safe-client.staging.5afe.dev/v1/chains/11155111/safes/0x5912f6616c84024cD1aff0D5b55bb36F5180fFdb/transactions/history?timezone=Europe/Berlin&trusted=false&cursor=limit=100&offset=1`
req.continue()
},
).as('allTransactions')
diff --git a/cypress/support/utils/txquery.js b/cypress/support/utils/txquery.js
index c4845de5ff..844501610b 100644
--- a/cypress/support/utils/txquery.js
+++ b/cypress/support/utils/txquery.js
@@ -9,7 +9,7 @@ function buildQueryUrl({ chainId, safeAddress, transactionType, ...params }) {
const defaultParams = {
safe: `sep:${safeAddress}`,
- timezone_offset: '7200000',
+ timezone: 'Europe/Berlin',
trusted: 'false',
}
diff --git a/package.json b/package.json
index f2adfc11cb..939757ef4e 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"@safe-global/protocol-kit": "^4.1.0",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-deployments": "^1.37.3",
- "@safe-global/safe-gateway-typescript-sdk": "3.22.2",
+ "@safe-global/safe-gateway-typescript-sdk": "3.22.4-beta.1",
"@safe-global/safe-modules-deployments": "^1.2.0",
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
diff --git a/src/services/transactions/index.tests.ts b/src/services/transactions/index.tests.ts
index 7b2634e075..d0310a8db0 100644
--- a/src/services/transactions/index.tests.ts
+++ b/src/services/transactions/index.tests.ts
@@ -1,8 +1,9 @@
-import { getTimezoneOffset } from '.'
+import { getTimezone } from '.'
-describe('getTimezoneOffset', () => {
- it('should return timezone offset in milliseconds', () => {
- const CET = 60 * 60 * 1000 // tests are run in CET
- expect(getTimezoneOffset()).toBe(-CET)
+describe('getTimezone', () => {
+ it('should return timezone', () => {
+ const result = getTimezone()
+
+ expect(result).toBeDefined()
})
})
diff --git a/src/services/transactions/index.ts b/src/services/transactions/index.ts
index bf4d7a39b1..9712dc9d89 100644
--- a/src/services/transactions/index.ts
+++ b/src/services/transactions/index.ts
@@ -1,6 +1,6 @@
import { getModuleTransactions, getTransactionHistory } from '@safe-global/safe-gateway-typescript-sdk'
-export const getTimezoneOffset = () => new Date().getTimezoneOffset() * 60 * -1000
+export const getTimezone = () => Intl.DateTimeFormat().resolvedOptions().timeZone
export const getTxHistory = (
chainId: string,
@@ -13,7 +13,7 @@ export const getTxHistory = (
chainId,
safeAddress,
{
- timezone_offset: getTimezoneOffset(), // used for grouping txs by date
+ timezone: getTimezone(), // used for grouping txs by date
// Untrusted and imitation txs are filtered together in the UI
trusted: hideUntrustedTxs, // if false, include transactions marked untrusted in the UI
imitation: !hideImitationTxs, // If true, include transactions marked imitation in the UI
diff --git a/src/utils/__tests__/tx-history-filter.test.ts b/src/utils/__tests__/tx-history-filter.test.ts
index 1c06e308f1..a2efaafd7a 100644
--- a/src/utils/__tests__/tx-history-filter.test.ts
+++ b/src/utils/__tests__/tx-history-filter.test.ts
@@ -19,6 +19,7 @@ import {
import { renderHook } from '@/tests/test-utils'
import type { NextRouter } from 'next/router'
import { type TxFilterFormState } from '@/components/transactions/TxFilterForm'
+import { getTimezone } from '@/services/transactions'
MockDate.set('2021-01-01T00:00:00.000Z')
@@ -395,7 +396,7 @@ describe('tx-history-filter', () => {
expect(getIncomingTransfers).toHaveBeenCalledWith(
'4',
'0x123',
- { value: '123', executed: undefined, timezone_offset: 3600000, trusted: false, imitation: true },
+ { value: '123', executed: undefined, timezone: getTimezone(), trusted: false, imitation: true },
'pageUrl1',
)
@@ -422,7 +423,7 @@ describe('tx-history-filter', () => {
{
execution_date__gte: '1970-01-01T00:00:00.000Z',
executed: 'true',
- timezone_offset: 3600000,
+ timezone: getTimezone(),
trusted: false,
imitation: true,
},
@@ -446,7 +447,7 @@ describe('tx-history-filter', () => {
expect(getModuleTransactions).toHaveBeenCalledWith(
'1',
'0x789',
- { to: '0x123', executed: undefined, timezone_offset: 3600000, trusted: false, imitation: true },
+ { to: '0x123', executed: undefined, timezone: getTimezone(), trusted: false, imitation: true },
'pageUrl3',
)
diff --git a/src/utils/tx-history-filter.ts b/src/utils/tx-history-filter.ts
index 016d1cd0f7..e6f4b8e1db 100644
--- a/src/utils/tx-history-filter.ts
+++ b/src/utils/tx-history-filter.ts
@@ -12,7 +12,7 @@ import { startOfDay, endOfDay } from 'date-fns'
import type { TxFilterFormState } from '@/components/transactions/TxFilterForm'
import { safeFormatUnits, safeParseUnits } from '@/utils/formatters'
-import { getTimezoneOffset } from '@/services/transactions'
+import { getTimezone } from '@/services/transactions'
type IncomingTxFilter = NonNullable
type MultisigTxFilter = NonNullable
@@ -126,7 +126,7 @@ export const fetchFilteredTxHistory = async (
const fetchPage = () => {
const query = {
...filterData.filter,
- timezone_offset: getTimezoneOffset(),
+ timezone: getTimezone(),
trusted: hideUntrustedTxs,
imitation: !hideImitationTxs,
executed: filterData.type === TxFilterType.MULTISIG ? 'true' : undefined,
diff --git a/yarn.lock b/yarn.lock
index 29c9a0c59f..2039d231b8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4183,10 +4183,10 @@
dependencies:
semver "^7.6.2"
-"@safe-global/safe-gateway-typescript-sdk@3.22.2":
- version "3.22.2"
- resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.2.tgz#d4ff9972e58f9344fc95f8d41b2ec6517baa8e79"
- integrity sha512-Y0yAxRaB98LFp2Dm+ACZqBSdAmI3FlpH/LjxOZ94g/ouuDJecSq0iR26XZ5QDuEL8Rf+L4jBJaoDC08CD0KkJw==
+"@safe-global/safe-gateway-typescript-sdk@3.22.4-beta.1":
+ version "3.22.4-beta.1"
+ resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.4-beta.1.tgz#ef8d0506d8c747124fae721a9baf99dda71af189"
+ integrity sha512-adxHiSeUc47MqkW7BM50U5xy6144rDEf0jyftzGXrBkG+nv/oL55SZQ/DdAsxyI1Mns02gzawa3Up+MfA8SKCQ==
"@safe-global/safe-gateway-typescript-sdk@^3.5.3":
version "3.21.2"
From d6539e189a5945a47d61ca8760408265b4e6886a Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Thu, 12 Sep 2024 11:57:35 +0200
Subject: [PATCH 63/81] Fix: update unverified token warning (#4155)
---
.../transactions/MaliciousTxWarning/index.tsx | 2 +-
.../TxDetails/TxData/Transfer/index.test.tsx | 18 +++++++++++-------
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/components/transactions/MaliciousTxWarning/index.tsx b/src/components/transactions/MaliciousTxWarning/index.tsx
index adbb973fb7..a77b14d725 100644
--- a/src/components/transactions/MaliciousTxWarning/index.tsx
+++ b/src/components/transactions/MaliciousTxWarning/index.tsx
@@ -3,7 +3,7 @@ import WarningIcon from '@/public/images/notifications/warning.svg'
const MaliciousTxWarning = ({ withTooltip = true }: { withTooltip?: boolean }) => {
return withTooltip ? (
-
+
diff --git a/src/components/transactions/TxDetails/TxData/Transfer/index.test.tsx b/src/components/transactions/TxDetails/TxData/Transfer/index.test.tsx
index d904372959..630e6f8f99 100644
--- a/src/components/transactions/TxDetails/TxData/Transfer/index.test.tsx
+++ b/src/components/transactions/TxDetails/TxData/Transfer/index.test.tsx
@@ -56,7 +56,7 @@ describe('TransferTxInfo', () => {
expect(result.getByText('1 TST')).toBeInTheDocument()
expect(result.getByText(recipient)).toBeInTheDocument()
expect(result.queryByText('malicious', { exact: false })).toBeNull()
- expect(result.queryByLabelText('This token is unfamiliar', { exact: false })).toBeNull()
+ expect(result.queryByLabelText('This token isn’t verified on major token lists', { exact: false })).toBeNull()
})
it('incoming tx', () => {
@@ -91,7 +91,7 @@ describe('TransferTxInfo', () => {
expect(result.getByText('12.34 TST')).toBeInTheDocument()
expect(result.getByText(sender)).toBeInTheDocument()
expect(result.queryByText('malicious', { exact: false })).toBeNull()
- expect(result.queryByLabelText('This token is unfamiliar', { exact: false })).toBeNull()
+ expect(result.queryByLabelText('This token isn’t verified on major token lists', { exact: false })).toBeNull()
})
})
@@ -128,7 +128,9 @@ describe('TransferTxInfo', () => {
expect(result.getByText('1 TST')).toBeInTheDocument()
expect(result.getByText(recipient)).toBeInTheDocument()
expect(result.queryByText('malicious', { exact: false })).toBeNull()
- expect(result.getByLabelText('This token is unfamiliar', { exact: false })).toBeInTheDocument()
+ expect(
+ result.getByLabelText('This token isn’t verified on major token lists', { exact: false }),
+ ).toBeInTheDocument()
})
it('incoming tx', () => {
@@ -163,7 +165,9 @@ describe('TransferTxInfo', () => {
expect(result.getByText('12.34 TST')).toBeInTheDocument()
expect(result.getByText(sender)).toBeInTheDocument()
expect(result.queryByText('malicious', { exact: false })).toBeNull()
- expect(result.queryByLabelText('This token is unfamiliar', { exact: false })).toBeInTheDocument()
+ expect(
+ result.queryByLabelText('This token isn’t verified on major token lists', { exact: false }),
+ ).toBeInTheDocument()
})
})
@@ -200,7 +204,7 @@ describe('TransferTxInfo', () => {
expect(result.getByText('1 TST')).toBeInTheDocument()
expect(result.getByText(recipient)).toBeInTheDocument()
expect(result.getByText('malicious', { exact: false })).toBeInTheDocument()
- expect(result.queryByLabelText('This token is unfamiliar', { exact: false })).toBeNull()
+ expect(result.queryByLabelText('This token isn’t verified on major token lists', { exact: false })).toBeNull()
})
it('incoming tx', () => {
@@ -235,7 +239,7 @@ describe('TransferTxInfo', () => {
expect(result.getByText('12.34 TST')).toBeInTheDocument()
expect(result.getByText(sender)).toBeInTheDocument()
expect(result.getByText('malicious', { exact: false })).toBeInTheDocument()
- expect(result.queryByLabelText('This token is unfamiliar', { exact: false })).toBeNull()
+ expect(result.queryByLabelText('This token isn’t verified on major token lists', { exact: false })).toBeNull()
})
it('untrusted and imitation tx', () => {
@@ -270,7 +274,7 @@ describe('TransferTxInfo', () => {
expect(result.getByText('12.34 TST')).toBeInTheDocument()
expect(result.getByText(sender)).toBeInTheDocument()
expect(result.getByText('malicious', { exact: false })).toBeInTheDocument()
- expect(result.queryByLabelText('This token is unfamiliar', { exact: false })).toBeNull()
+ expect(result.queryByLabelText('This token isn’t verified on major token lists', { exact: false })).toBeNull()
})
})
})
From 502e36f75211ae85242e8f67e73bdaa01f78f5ad Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Thu, 12 Sep 2024 12:18:28 +0200
Subject: [PATCH 64/81] 1.42.0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index f2adfc11cb..e25226eff5 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.41.5",
+ "version": "1.42.0",
"type": "module",
"scripts": {
"dev": "next dev",
From 2fcd8fcd8203323d6ecc3275098a5f86fbc7d4ca Mon Sep 17 00:00:00 2001
From: Daniel Dimitrov
Date: Thu, 12 Sep 2024 15:49:57 +0200
Subject: [PATCH 65/81] Feat: Kiln widget (#3962)
* feat: experiment with kiln widget
* feat: add stake concent warning
* fix: wrong widget url
* feat: add theme support for staking widget
* fix: use https address
* Decoding + ifram tweaks
* OrderConfirmationView
* Switch the widget to testnet
* Format values
* Fix types
* TokenInfoPair
* Fix hydration errors with legal disclaimer
* New widget URL
* Pass value to getConfirmationView
* Fix double request for confirmation view
* Update Stake icon
* Token info from the API
* Hide method call for staking orders
* Update confirmation view types
* Display rewards in fiat
* Custom icon for deposits
* Tx details
* Fix type
* Fix tests
* Extract formatSeconds
* Status chips
* Reuse StakingOrderConfirmationView
* Flat style in tx details
* Geoblocking
* Feature toggles and geoblocking
* Move twap module warning to swap order view
* Hide queue bar
* New label in sidebar
* Capitalize status labels
* Fix unit test
* Reuse widget disclaimer component
* Adjust type
* Unify status chips
* Keep queue bar on the stake page
* TokenInfoPair -> ConfirmationOrderHeader
* Fix status chip style
* Rm sidebar tooltip
* feat: add decoding for withdraw request
.
* fix: failing tests
---------
Co-authored-by: katspaugh
Co-authored-by: katspaugh <381895+katspaugh@users.noreply.github.com>
---
package.json | 2 +-
.../common/WidgetDisclaimer}/index.tsx | 14 ++-
.../WidgetDisclaimer}/styles.module.css | 0
src/components/dashboard/Assets/index.tsx | 2 +-
src/components/safe-apps/AppFrame/index.tsx | 26 +++---
.../sidebar/SidebarNavigation/config.tsx | 5 +-
.../sidebar/SidebarNavigation/index.tsx | 48 +++++-----
.../TrustedToggle/TrustedToggleButton.tsx | 2 +-
.../transactions/TxDetails/Summary/index.tsx | 11 ++-
.../transactions/TxDetails/TxData/index.tsx | 18 ++++
.../transactions/TxDetails/index.tsx | 9 --
.../transactions/TxDetails/styles.module.css | 18 +---
src/components/transactions/TxInfo/index.tsx | 20 +++-
.../transactions/TxStatusChip/index.tsx | 23 +++--
.../tx-flow/flows/SignMessage/index.tsx | 11 ++-
.../tx/AdvancedParams/AdvancedParamsForm.tsx | 2 +-
.../ConfirmationOrderHeader.tsx | 77 ++++++++++++++++
src/components/tx/ConfirmationOrder/index.tsx | 23 +++++
src/components/tx/DecodedTx/index.tsx | 4 +-
src/components/tx/GasParams/index.tsx | 2 +-
src/components/tx/SignOrExecuteForm/index.tsx | 19 ++--
src/config/routes.ts | 2 +-
.../recovery/hooks/useIsRecoverySupported.ts | 2 +-
.../stake/components/StakePage/index.tsx | 28 ++++++
.../StakingConfirmationTx/Deposit.tsx | 91 +++++++++++++++++++
.../components/StakingConfirmationTx/Exit.tsx | 48 ++++++++++
.../StakingConfirmationTx/index.tsx | 25 +++++
.../stake/components/StakingStatus/index.tsx | 77 ++++++++++++++++
.../StakingTxDepositDetails/index.tsx | 21 +++++
.../components/StakingTxDepositInfo/index.tsx | 8 ++
.../components/StakingTxExitDetails/index.tsx | 34 +++++++
.../components/StakingTxExitInfo/index.tsx | 17 ++++
.../stake/components/StakingWidget/index.tsx | 35 +++++++
src/features/stake/constants.ts | 1 +
src/features/stake/helpers/utils.ts | 17 ++++
src/features/stake/useStakeConsent.ts | 28 ++++++
.../swap/components/StatusLabel/index.tsx | 50 +++-------
.../OrderFeeConfirmationView.tsx | 8 +-
.../SwapOrderConfirmationView/index.tsx | 28 +++---
.../components/SwapTokens/index.stories.tsx | 18 ++--
.../swap/components/SwapTokens/index.tsx | 52 +----------
.../components/SwapTokens/styles.module.css | 32 -------
.../TwapFallbackHandlerWarning/index.tsx | 20 ++--
src/features/swap/index.tsx | 21 ++---
src/hooks/__tests__/useDecodeTx.test.ts | 3 +-
src/hooks/useChains.ts | 4 +-
src/hooks/useDecodeTx.ts | 34 +++----
src/hooks/useTransactionType.tsx | 24 +++--
src/pages/stake.tsx | 32 +++++++
src/pages/swap.tsx | 27 +++---
src/services/tx/extractTxInfo.ts | 10 ++
src/services/tx/tokenTransferParams.ts | 12 ++-
src/styles/globals.css | 4 -
src/utils/__tests__/transactions.test.ts | 9 ++
src/utils/chains.ts | 4 +-
src/utils/formatters.ts | 9 ++
src/utils/transaction-guards.ts | 63 +++++++++++--
src/utils/transactions.ts | 3 +-
src/utils/url.ts | 18 +++-
yarn.lock | 39 ++------
60 files changed, 938 insertions(+), 356 deletions(-)
rename src/{features/swap/components/LegalDisclaimer => components/common/WidgetDisclaimer}/index.tsx (77%)
rename src/{features/swap/components/LegalDisclaimer => components/common/WidgetDisclaimer}/styles.module.css (100%)
create mode 100644 src/components/tx/ConfirmationOrder/ConfirmationOrderHeader.tsx
create mode 100644 src/components/tx/ConfirmationOrder/index.tsx
create mode 100644 src/features/stake/components/StakePage/index.tsx
create mode 100644 src/features/stake/components/StakingConfirmationTx/Deposit.tsx
create mode 100644 src/features/stake/components/StakingConfirmationTx/Exit.tsx
create mode 100644 src/features/stake/components/StakingConfirmationTx/index.tsx
create mode 100644 src/features/stake/components/StakingStatus/index.tsx
create mode 100644 src/features/stake/components/StakingTxDepositDetails/index.tsx
create mode 100644 src/features/stake/components/StakingTxDepositInfo/index.tsx
create mode 100644 src/features/stake/components/StakingTxExitDetails/index.tsx
create mode 100644 src/features/stake/components/StakingTxExitInfo/index.tsx
create mode 100644 src/features/stake/components/StakingWidget/index.tsx
create mode 100644 src/features/stake/constants.ts
create mode 100644 src/features/stake/helpers/utils.ts
create mode 100644 src/features/stake/useStakeConsent.ts
delete mode 100644 src/features/swap/components/SwapTokens/styles.module.css
create mode 100644 src/pages/stake.tsx
diff --git a/package.json b/package.json
index 939757ef4e..c7e12fa92f 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"@safe-global/protocol-kit": "^4.1.0",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-deployments": "^1.37.3",
- "@safe-global/safe-gateway-typescript-sdk": "3.22.4-beta.1",
+ "@safe-global/safe-gateway-typescript-sdk": "3.22.3-beta.12",
"@safe-global/safe-modules-deployments": "^1.2.0",
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
diff --git a/src/features/swap/components/LegalDisclaimer/index.tsx b/src/components/common/WidgetDisclaimer/index.tsx
similarity index 77%
rename from src/features/swap/components/LegalDisclaimer/index.tsx
rename to src/components/common/WidgetDisclaimer/index.tsx
index a324af6889..3c5969d784 100644
--- a/src/features/swap/components/LegalDisclaimer/index.tsx
+++ b/src/components/common/WidgetDisclaimer/index.tsx
@@ -4,7 +4,11 @@ import { Typography } from '@mui/material'
import css from './styles.module.css'
-const LegalDisclaimerContent = () => (
+const linkSx = {
+ textDecoration: 'none',
+}
+
+const WidgetDisclaimer = ({ widgetName }: { widgetName: string }) => (
@@ -12,21 +16,21 @@ const LegalDisclaimerContent = () => (
- Please note that we do not own, control, maintain or audit the CoW Swap Widget. Use of the widget is subject to
+ Please note that we do not own, control, maintain or audit the {widgetName}. Use of the widget is subject to
third party terms & conditions. We are not liable for any loss you may suffer in connection with interacting
with the widget, which is at your own risk.
Our{' '}
-
+
terms
{' '}
contain more detailed provisions binding on you relating to such third party content.
By clicking "continue" you re-confirm to have read and understood our{' '}
-
+
terms
{' '}
and this message, and agree to them.
@@ -35,4 +39,4 @@ const LegalDisclaimerContent = () => (
)
-export default LegalDisclaimerContent
+export default WidgetDisclaimer
diff --git a/src/features/swap/components/LegalDisclaimer/styles.module.css b/src/components/common/WidgetDisclaimer/styles.module.css
similarity index 100%
rename from src/features/swap/components/LegalDisclaimer/styles.module.css
rename to src/components/common/WidgetDisclaimer/styles.module.css
diff --git a/src/components/dashboard/Assets/index.tsx b/src/components/dashboard/Assets/index.tsx
index 8df89c1644..12aca61614 100644
--- a/src/components/dashboard/Assets/index.tsx
+++ b/src/components/dashboard/Assets/index.tsx
@@ -43,7 +43,7 @@ const NoAssets = () => (
)
-const AssetRow = ({ item, showSwap }: { item: SafeBalanceResponse['items'][number]; showSwap: boolean }) => (
+const AssetRow = ({ item, showSwap }: { item: SafeBalanceResponse['items'][number]; showSwap?: boolean }) => (
{
+const AppFrame = ({ appUrl, allowedFeaturesList, safeAppFromManifest, isNativeEmbed }: AppFrameProps): ReactElement => {
const { safe, safeLoaded } = useSafeInfo()
const addressBook = useAddressBook()
const chainId = useChainId()
@@ -98,11 +97,14 @@ const AppFrame = ({ appUrl, allowedFeaturesList, safeAppFromManifest }: AppFrame
}
setAppIsLoading(false)
- gtmTrackPageview(`${router.pathname}?appUrl=${router.query.appUrl}`, router.asPath)
- }, [appUrl, iframeRef, setAppIsLoading, router])
+
+ if (!isNativeEmbed) {
+ gtmTrackPageview(`${router.pathname}?appUrl=${router.query.appUrl}`, router.asPath)
+ }
+ }, [appUrl, iframeRef, setAppIsLoading, router, isNativeEmbed])
useEffect(() => {
- if (!appIsLoading && !isBackendAppsLoading) {
+ if (!isNativeEmbed && !appIsLoading && !isBackendAppsLoading) {
trackSafeAppEvent(
{
...SAFE_APPS_EVENTS.OPEN_APP,
@@ -110,7 +112,7 @@ const AppFrame = ({ appUrl, allowedFeaturesList, safeAppFromManifest }: AppFrame
appName,
)
}
- }, [appIsLoading, isBackendAppsLoading, appName])
+ }, [appIsLoading, isBackendAppsLoading, appName, isNativeEmbed])
if (!safeLoaded) {
return
@@ -118,9 +120,11 @@ const AppFrame = ({ appUrl, allowedFeaturesList, safeAppFromManifest }: AppFrame
return (
<>
-
- {`Safe Apps - Viewer - ${remoteApp ? remoteApp.name : UNKNOWN_APP_NAME}`}
-
+ {!isNativeEmbed && (
+
+ {`Safe{Wallet} - Safe Apps${remoteApp ? ' - ' + remoteApp.name : ''}`}
+
+ )}
{thirdPartyCookiesDisabled &&
setThirdPartyCookiesDisabled(false)} />}
@@ -160,7 +164,7 @@ const AppFrame = ({ appUrl, allowedFeaturesList, safeAppFromManifest }: AppFrame
transactions={transactions}
/>
- {permissionsRequest && (
+ {!isNativeEmbed && permissionsRequest && (
,
href: AppRoutes.stake,
- tag: ,
- disabled: true,
- tooltip: 'Native staking is coming soon, stay tuned!',
+ tag: ,
},
{
label: 'Transactions',
diff --git a/src/components/sidebar/SidebarNavigation/index.tsx b/src/components/sidebar/SidebarNavigation/index.tsx
index d7b38f8544..c5980ba59a 100644
--- a/src/components/sidebar/SidebarNavigation/index.tsx
+++ b/src/components/sidebar/SidebarNavigation/index.tsx
@@ -19,12 +19,13 @@ import { isRouteEnabled } from '@/utils/chains'
import { trackEvent } from '@/services/analytics'
import { SWAP_EVENTS, SWAP_LABELS } from '@/services/analytics/events/swaps'
import { GeoblockingContext } from '@/components/common/GeoblockingProvider'
-import { Tooltip } from '@mui/material'
const getSubdirectory = (pathname: string): string => {
return pathname.split('/')[1]
}
+const geoBlockedRoutes = [AppRoutes.swap, AppRoutes.stake]
+
const Navigation = (): ReactElement => {
const chain = useCurrentChain()
const router = useRouter()
@@ -32,14 +33,14 @@ const Navigation = (): ReactElement => {
const currentSubdirectory = getSubdirectory(router.pathname)
const queueSize = useQueuedTxsLength()
const isBlockedCountry = useContext(GeoblockingContext)
+
const enabledNavItems = useMemo(() => {
return navItems.filter((item) => {
- const enabled = isRouteEnabled(item.href, chain)
-
- if (item.href === AppRoutes.swap && isBlockedCountry) {
+ if (isBlockedCountry && geoBlockedRoutes.includes(item.href)) {
return false
}
- return enabled
+
+ return isRouteEnabled(item.href, chain)
})
}, [chain, isBlockedCountry])
@@ -76,23 +77,26 @@ const Navigation = (): ReactElement => {
}
return (
-
- handleNavigationClick(item.href)}>
-
- {item.icon && {item.icon} }
-
-
- {item.label}
-
- {ItemTag}
-
-
-
-
+ handleNavigationClick(item.href)}
+ key={item.href}
+ >
+
+ {item.icon && {item.icon} }
+
+
+ {item.label}
+
+ {ItemTag}
+
+
+
)
})}
diff --git a/src/components/transactions/TrustedToggle/TrustedToggleButton.tsx b/src/components/transactions/TrustedToggle/TrustedToggleButton.tsx
index c5bc393a8d..918d64d91f 100644
--- a/src/components/transactions/TrustedToggle/TrustedToggleButton.tsx
+++ b/src/components/transactions/TrustedToggle/TrustedToggleButton.tsx
@@ -10,7 +10,7 @@ const _TrustedToggleButton = ({
}: {
onlyTrusted: boolean
setOnlyTrusted: (on: boolean) => void
- hasDefaultTokenlist: boolean
+ hasDefaultTokenlist?: boolean
}): ReactElement | null => {
const onClick = () => {
setOnlyTrusted(!onlyTrusted)
diff --git a/src/components/transactions/TxDetails/Summary/index.tsx b/src/components/transactions/TxDetails/Summary/index.tsx
index 45c92e1b25..bd87099a66 100644
--- a/src/components/transactions/TxDetails/Summary/index.tsx
+++ b/src/components/transactions/TxDetails/Summary/index.tsx
@@ -2,13 +2,14 @@ import type { ReactElement } from 'react'
import React, { useState } from 'react'
import { Link, Box } from '@mui/material'
import { generateDataRowValue, TxDataRow } from '@/components/transactions/TxDetails/Summary/TxDataRow'
-import { isMultisigDetailedExecutionInfo } from '@/utils/transaction-guards'
+import { isCustomTxInfo, isMultisigDetailedExecutionInfo } from '@/utils/transaction-guards'
import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
import { Operation } from '@safe-global/safe-gateway-typescript-sdk'
import { dateString } from '@/utils/formatters'
import css from './styles.module.css'
import type { SafeTransaction } from '@safe-global/safe-core-sdk-types'
import SafeTxGasForm from '../SafeTxGasForm'
+import DecodedData from '../TxData/DecodedData'
interface Props {
txDetails: TransactionDetails
@@ -30,6 +31,8 @@ const Summary = ({ txDetails, defaultExpanded = false }: Props): ReactElement =>
refundReceiver = detailedExecutionInfo.refundReceiver?.value
}
+ const isCustom = isCustomTxInfo(txDetails.txInfo)
+
return (
<>
{txHash && (
@@ -67,6 +70,12 @@ const Summary = ({ txDetails, defaultExpanded = false }: Props): ReactElement =>
{expanded && (
+ {!isCustom && (
+
+
+
+ )}
+
{`${txData.operation} (${Operation[txData.operation].toLowerCase()})`}
diff --git a/src/components/transactions/TxDetails/TxData/index.tsx b/src/components/transactions/TxDetails/TxData/index.tsx
index a19e55bc69..a197b02818 100644
--- a/src/components/transactions/TxDetails/TxData/index.tsx
+++ b/src/components/transactions/TxDetails/TxData/index.tsx
@@ -1,11 +1,14 @@
import SettingsChangeTxInfo from '@/components/transactions/TxDetails/TxData/SettingsChange'
import type { SpendingLimitMethods } from '@/utils/transaction-guards'
+import { isStakingTxExitInfo } from '@/utils/transaction-guards'
import {
isCancellationTxInfo,
isCustomTxInfo,
isMultisigDetailedExecutionInfo,
+ isOrderTxInfo,
isSettingsChangeTxInfo,
isSpendingLimitMethod,
+ isStakingTxDepositInfo,
isSupportedSpendingLimitAddress,
isTransferTxInfo,
} from '@/utils/transaction-guards'
@@ -16,6 +19,9 @@ import RejectionTxInfo from '@/components/transactions/TxDetails/TxData/Rejectio
import DecodedData from '@/components/transactions/TxDetails/TxData/DecodedData'
import TransferTxInfo from '@/components/transactions/TxDetails/TxData/Transfer'
import useChainId from '@/hooks/useChainId'
+import SwapOrder from '@/features/swap/components/SwapOrder'
+import StakingTxDepositDetails from '@/features/stake/components/StakingTxDepositDetails'
+import StakingTxExitDetails from '@/features/stake/components/StakingTxExitDetails'
const TxData = ({
txDetails,
@@ -30,6 +36,18 @@ const TxData = ({
const txInfo = txDetails.txInfo
const toInfo = isCustomTxInfo(txDetails.txInfo) ? txDetails.txInfo.to : undefined
+ if (isOrderTxInfo(txDetails.txInfo)) {
+ return
+ }
+
+ if (isStakingTxDepositInfo(txDetails.txInfo)) {
+ return
+ }
+
+ if (isStakingTxExitInfo(txDetails.txInfo)) {
+ return
+ }
+
if (isTransferTxInfo(txInfo)) {
return
}
diff --git a/src/components/transactions/TxDetails/index.tsx b/src/components/transactions/TxDetails/index.tsx
index 1d9a4febf4..1387362d0b 100644
--- a/src/components/transactions/TxDetails/index.tsx
+++ b/src/components/transactions/TxDetails/index.tsx
@@ -33,7 +33,6 @@ import useIsPending from '@/hooks/useIsPending'
import { isImitation, isTrustedTx } from '@/utils/transactions'
import { useHasFeature } from '@/hooks/useChains'
import { FEATURES } from '@/utils/chains'
-import { SwapOrder } from '@/features/swap/components/SwapOrder'
import { useGetTransactionDetailsQuery } from '@/store/gateway'
import { asError } from '@/services/exceptions/utils'
import { POLLING_INTERVAL } from '@/config/constants'
@@ -77,14 +76,6 @@ const TxDetailsBlock = ({ txSummary, txDetails }: TxDetailsProps): ReactElement
<>
{/* /Details */}
- {isOrderTxInfo(txDetails.txInfo) && (
-
- Error parsing data
}>
-
-
-
- )}
-
diff --git a/src/components/transactions/TxDetails/styles.module.css b/src/components/transactions/TxDetails/styles.module.css
index 9d9e8de2b4..5c3bc427dc 100644
--- a/src/components/transactions/TxDetails/styles.module.css
+++ b/src/components/transactions/TxDetails/styles.module.css
@@ -22,22 +22,11 @@
.txData,
.txSummary,
.advancedDetails,
-.txModule,
-.swapOrder {
+.txModule {
padding: var(--space-2);
}
-.swapOrderTransfer {
- border-top: 1px solid var(--color-border-light);
- margin-top: var(--space-2);
- margin-left: calc(var(--space-2) * -1);
- margin-right: calc(var(--space-2) * -1);
- padding: var(--space-2);
- padding-top: var(--space-3);
-}
-
-.txData,
-.swapOrder {
+.txData {
border-bottom: 1px solid var(--color-border-light);
}
@@ -59,8 +48,7 @@
padding: 0 var(--space-1);
}
-.multiSend,
-.swapOrder {
+.multiSend {
border-bottom: 1px solid var(--color-border-light);
}
diff --git a/src/components/transactions/TxInfo/index.tsx b/src/components/transactions/TxInfo/index.tsx
index 8dbd055ddd..f5f12fdf22 100644
--- a/src/components/transactions/TxInfo/index.tsx
+++ b/src/components/transactions/TxInfo/index.tsx
@@ -19,12 +19,16 @@ import {
isNativeTokenTransfer,
isSettingsChangeTxInfo,
isTransferTxInfo,
+ isStakingTxDepositInfo,
+ isStakingTxExitInfo,
} from '@/utils/transaction-guards'
import { ellipsis, shortenAddress } from '@/utils/formatters'
import { useCurrentChain } from '@/hooks/useChains'
import { SwapTx } from '@/features/swap/components/SwapTxInfo/SwapTx'
+import StakingTxExitInfo from '@/features/stake/components/StakingTxExitInfo'
import { Box } from '@mui/material'
import css from './styles.module.css'
+import StakingTxDepositInfo from '@/features/stake/components/StakingTxDepositInfo'
export const TransferTx = ({
info,
@@ -125,10 +129,6 @@ const TxInfo = ({ info, ...rest }: { info: TransactionInfo; omitSign?: boolean;
return
}
- if (isCustomTxInfo(info)) {
- return
- }
-
if (isCreationTxInfo(info)) {
return
}
@@ -137,6 +137,18 @@ const TxInfo = ({ info, ...rest }: { info: TransactionInfo; omitSign?: boolean;
return
}
+ if (isStakingTxDepositInfo(info)) {
+ return
+ }
+
+ if (isStakingTxExitInfo(info)) {
+ return
+ }
+
+ if (isCustomTxInfo(info)) {
+ return
+ }
+
return <>>
}
diff --git a/src/components/transactions/TxStatusChip/index.tsx b/src/components/transactions/TxStatusChip/index.tsx
index c9bb49c874..339236fb75 100644
--- a/src/components/transactions/TxStatusChip/index.tsx
+++ b/src/components/transactions/TxStatusChip/index.tsx
@@ -1,19 +1,28 @@
import type { ReactElement, ReactNode } from 'react'
import { Typography, Chip } from '@mui/material'
-const TxStatusChip = ({
- children,
- color,
-}: {
+export type TxStatusChipProps = {
children: ReactNode
color?: 'primary' | 'secondary' | 'info' | 'warning' | 'success' | 'error'
-}): ReactElement => {
+}
+
+const TxStatusChip = ({ children, color }: TxStatusChipProps): ReactElement => {
return (
+
{children}
}
diff --git a/src/components/tx-flow/flows/SignMessage/index.tsx b/src/components/tx-flow/flows/SignMessage/index.tsx
index ac9503ef59..6c608ba339 100644
--- a/src/components/tx-flow/flows/SignMessage/index.tsx
+++ b/src/components/tx-flow/flows/SignMessage/index.tsx
@@ -8,6 +8,8 @@ import SafeAppIconCard from '@/components/safe-apps/SafeAppIconCard'
import { ErrorBoundary } from '@sentry/react'
import { type BaseTransaction } from '@safe-global/safe-apps-sdk'
import { SWAP_TITLE } from '@/features/swap/constants'
+import { STAKE_TITLE } from '@/features/stake/constants'
+import { getStakeTitle } from '@/features/stake/helpers/utils'
const APP_LOGO_FALLBACK_IMAGE = '/images/apps/apps-icon.svg'
const APP_NAME_FALLBACK = 'Sign message'
@@ -26,7 +28,14 @@ export const AppTitle = ({
const appName = name || APP_NAME_FALLBACK
const appLogo = logoUri || APP_LOGO_FALLBACK_IMAGE
- const title = name === SWAP_TITLE ? getSwapTitle(swapParams.tradeType, txs) : appName
+ let title = appName
+ if (name === SWAP_TITLE) {
+ title = getSwapTitle(swapParams.tradeType, txs) || title
+ }
+
+ if (name === STAKE_TITLE) {
+ title = getStakeTitle(txs) || title
+ }
return (
diff --git a/src/components/tx/AdvancedParams/AdvancedParamsForm.tsx b/src/components/tx/AdvancedParams/AdvancedParamsForm.tsx
index 9e1ae1c838..a01ea2c64a 100644
--- a/src/components/tx/AdvancedParams/AdvancedParamsForm.tsx
+++ b/src/components/tx/AdvancedParams/AdvancedParamsForm.tsx
@@ -15,7 +15,7 @@ type AdvancedParamsFormProps = {
onSubmit: (params: AdvancedParameters) => void
recommendedGasLimit?: AdvancedParameters['gasLimit']
isExecution: boolean
- isEIP1559: boolean
+ isEIP1559?: boolean
willRelay?: boolean
}
diff --git a/src/components/tx/ConfirmationOrder/ConfirmationOrderHeader.tsx b/src/components/tx/ConfirmationOrder/ConfirmationOrderHeader.tsx
new file mode 100644
index 0000000000..89b09f0fd3
--- /dev/null
+++ b/src/components/tx/ConfirmationOrder/ConfirmationOrderHeader.tsx
@@ -0,0 +1,77 @@
+import { Stack, Box, Typography, SvgIcon } from '@mui/material'
+import EastRoundedIcon from '@mui/icons-material/EastRounded'
+import TokenIcon from '@/components/common/TokenIcon'
+import TokenAmount from '@/components/common/TokenAmount'
+
+export type InfoBlock = {
+ value: string
+ label: string
+ tokenInfo?: {
+ decimals: number
+ symbol: string
+ logoUri?: string | null
+ }
+}
+
+const ConfirmationOrderHeader = ({ blocks, showArrow }: { blocks: [InfoBlock, InfoBlock]; showArrow?: boolean }) => {
+ return (
+
+ {blocks.map((block, index) => (
+
+ {block.tokenInfo && (
+
+
+
+ )}
+
+
+
+ {block.label}
+
+
+
+ {block.tokenInfo ? (
+
+ ) : (
+ block.value
+ )}
+
+
+
+ {showArrow && index === 0 && (
+
+
+
+ )}
+
+ ))}
+
+ )
+}
+
+export default ConfirmationOrderHeader
diff --git a/src/components/tx/ConfirmationOrder/index.tsx b/src/components/tx/ConfirmationOrder/index.tsx
new file mode 100644
index 0000000000..33142de06f
--- /dev/null
+++ b/src/components/tx/ConfirmationOrder/index.tsx
@@ -0,0 +1,23 @@
+import StrakingConfirmationTx from '@/features/stake/components/StakingConfirmationTx'
+import SwapOrderConfirmationView from '@/features/swap/components/SwapOrderConfirmationView'
+import type useDecodeTx from '@/hooks/useDecodeTx'
+import { isAnyStakingConfirmationView, isAnySwapConfirmationViewOrder } from '@/utils/transaction-guards'
+
+type OrderConfirmationViewProps = {
+ decodedData: ReturnType[0]
+ toAddress: string
+}
+
+const ConfirmationOrder = ({ decodedData, toAddress }: OrderConfirmationViewProps) => {
+ if (isAnySwapConfirmationViewOrder(decodedData)) {
+ return
+ }
+
+ if (isAnyStakingConfirmationView(decodedData)) {
+ return
+ }
+
+ return null
+}
+
+export default ConfirmationOrder
diff --git a/src/components/tx/DecodedTx/index.tsx b/src/components/tx/DecodedTx/index.tsx
index ac3ddfcd8e..44d8c3087a 100644
--- a/src/components/tx/DecodedTx/index.tsx
+++ b/src/components/tx/DecodedTx/index.tsx
@@ -41,9 +41,9 @@ const DecodedTx = ({
showMultisend = true,
showMethodCall = false,
}: DecodedTxProps): ReactElement => {
- const isMultisend = !!decodedData?.parameters?.[0]?.valueDecoded
const chainId = useChainId()
- const isMethodCallInAdvanced = !showMethodCall || isMultisend
+ const isMultisend = !!decodedData?.parameters?.[0]?.valueDecoded
+ const isMethodCallInAdvanced = !showMethodCall || (isMultisend && showMultisend)
const {
data: txDetails,
diff --git a/src/components/tx/GasParams/index.tsx b/src/components/tx/GasParams/index.tsx
index 9aaabf6a94..3510cb1d88 100644
--- a/src/components/tx/GasParams/index.tsx
+++ b/src/components/tx/GasParams/index.tsx
@@ -28,7 +28,7 @@ const GasDetail = ({ name, value, isLoading }: { name: string; value: string; is
type GasParamsProps = {
params: AdvancedParameters
isExecution: boolean
- isEIP1559: boolean
+ isEIP1559?: boolean
onEdit?: () => void
gasLimitError?: Error
willRelay?: boolean
diff --git a/src/components/tx/SignOrExecuteForm/index.tsx b/src/components/tx/SignOrExecuteForm/index.tsx
index e830e75db9..2a493b05bd 100644
--- a/src/components/tx/SignOrExecuteForm/index.tsx
+++ b/src/components/tx/SignOrExecuteForm/index.tsx
@@ -27,15 +27,13 @@ import { trackEvent } from '@/services/analytics'
import useChainId from '@/hooks/useChainId'
import ExecuteThroughRoleForm from './ExecuteThroughRoleForm'
import { findAllowingRole, findMostLikelyRole, useRoles } from './ExecuteThroughRoleForm/hooks'
-import { isConfirmationViewOrder, isCustomTxInfo } from '@/utils/transaction-guards'
-import SwapOrderConfirmationView from '@/features/swap/components/SwapOrderConfirmationView'
-import { isSettingTwapFallbackHandler } from '@/features/swap/helpers/utils'
-import { TwapFallbackHandlerWarning } from '@/features/swap/components/TwapFallbackHandlerWarning'
+import { isCustomTxInfo, isGenericConfirmation } from '@/utils/transaction-guards'
import useIsSafeOwner from '@/hooks/useIsSafeOwner'
import { BlockaidBalanceChanges } from '../security/blockaid/BlockaidBalanceChange'
import { Blockaid } from '../security/blockaid'
import TxData from '@/components/transactions/TxDetails/TxData'
+import ConfirmationOrder from '@/components/tx/ConfirmationOrder'
import { useApprovalInfos } from '../ApprovalEditor/hooks/useApprovalInfos'
import type { TransactionDetails } from '@safe-global/safe-gateway-typescript-sdk'
@@ -97,7 +95,7 @@ export const SignOrExecuteForm = ({
const [decodedData] = useDecodeTx(safeTx)
const isBatchable = props.isBatchable !== false && safeTx && !isDelegateCall(safeTx)
- const isSwapOrder = isConfirmationViewOrder(decodedData)
+
const { data: txDetails } = useGetTransactionDetailsQuery(
chainId && props.txId
? {
@@ -115,7 +113,6 @@ export const SignOrExecuteForm = ({
const { safe } = useSafeInfo()
const isSafeOwner = useIsSafeOwner()
const isCounterfactualSafe = !safe.deployed
- const isChangingFallbackHandler = isSettingTwapFallbackHandler(decodedData)
// Check if a Zodiac Roles mod is enabled and if the user is a member of any role that allows the transaction
const roles = useRoles(
@@ -153,11 +150,9 @@ export const SignOrExecuteForm = ({
{props.children}
- {isChangingFallbackHandler && }
-
- {isSwapOrder && (
+ {decodedData && (
>}>
-
+
)}
@@ -172,7 +167,9 @@ export const SignOrExecuteForm = ({
txId={props.txId}
decodedData={decodedData}
showMultisend={!props.isBatch}
- showMethodCall={props.showMethodCall && !showTxDetails && !isSwapOrder && !isApproval}
+ showMethodCall={
+ props.showMethodCall && !showTxDetails && !isApproval && isGenericConfirmation(decodedData)
+ }
/>
)}
diff --git a/src/config/routes.ts b/src/config/routes.ts
index 0509085fa5..8f65fa5bb7 100644
--- a/src/config/routes.ts
+++ b/src/config/routes.ts
@@ -4,6 +4,7 @@ export const AppRoutes = {
wc: '/wc',
terms: '/terms',
swap: '/swap',
+ stake: '/stake',
privacy: '/privacy',
licenses: '/licenses',
index: '/',
@@ -45,7 +46,6 @@ export const AppRoutes = {
share: {
safeApp: '/share/safe-app',
},
- stake: '/stake',
transactions: {
tx: '/transactions/tx',
queue: '/transactions/queue',
diff --git a/src/features/recovery/hooks/useIsRecoverySupported.ts b/src/features/recovery/hooks/useIsRecoverySupported.ts
index 099578df0c..549070dea7 100644
--- a/src/features/recovery/hooks/useIsRecoverySupported.ts
+++ b/src/features/recovery/hooks/useIsRecoverySupported.ts
@@ -2,5 +2,5 @@ import { useHasFeature } from '@/hooks/useChains'
import { FEATURES } from '@/utils/chains'
export function useIsRecoverySupported(): boolean {
- return useHasFeature(FEATURES.RECOVERY)
+ return useHasFeature(FEATURES.RECOVERY) ?? false
}
diff --git a/src/features/stake/components/StakePage/index.tsx b/src/features/stake/components/StakePage/index.tsx
new file mode 100644
index 0000000000..7ab3382e1e
--- /dev/null
+++ b/src/features/stake/components/StakePage/index.tsx
@@ -0,0 +1,28 @@
+import { Stack } from '@mui/material'
+import Disclaimer from '@/components/common/Disclaimer'
+import WidgetDisclaimer from '@/components/common/WidgetDisclaimer'
+import useStakeConsent from '@/features/stake/useStakeConsent'
+import StakingWidget from '../StakingWidget'
+
+const StakePage = () => {
+ const { isConsentAccepted, onAccept } = useStakeConsent()
+
+ return (
+ <>
+ {isConsentAccepted === undefined ? null : isConsentAccepted ? (
+
+ ) : (
+
+ }
+ onAccept={onAccept}
+ buttonText="Continue"
+ />
+
+ )}
+ >
+ )
+}
+
+export default StakePage
diff --git a/src/features/stake/components/StakingConfirmationTx/Deposit.tsx b/src/features/stake/components/StakingConfirmationTx/Deposit.tsx
new file mode 100644
index 0000000000..c7fccc3fc2
--- /dev/null
+++ b/src/features/stake/components/StakingConfirmationTx/Deposit.tsx
@@ -0,0 +1,91 @@
+import { Typography, Stack, Box } from '@mui/material'
+import FieldsGrid from '@/components/tx/FieldsGrid'
+import type { StakingTxDepositInfo } from '@safe-global/safe-gateway-typescript-sdk'
+import {
+ ConfirmationViewTypes,
+ type NativeStakingDepositConfirmationView,
+} from '@safe-global/safe-gateway-typescript-sdk'
+import ConfirmationOrderHeader from '@/components/tx/ConfirmationOrder/ConfirmationOrderHeader'
+import { formatVisualAmount, formatDurationFromSeconds } from '@/utils/formatters'
+import { formatCurrency } from '@/utils/formatNumber'
+import StakingStatus from '@/features/stake/components/StakingStatus'
+
+type StakingOrderConfirmationViewProps = {
+ order: NativeStakingDepositConfirmationView | StakingTxDepositInfo
+}
+
+const CURRENCY = 'USD'
+
+const StakingConfirmationTxDeposit = ({ order }: StakingOrderConfirmationViewProps) => {
+ const isOrder = order.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_DEPOSIT
+
+ return (
+
+ {isOrder && (
+
+ )}
+
+
+ {formatVisualAmount(order.expectedAnnualReward, order.tokenInfo.decimals)} {order.tokenInfo.symbol}
+ {' ('}
+ {formatCurrency(order.expectedFiatAnnualReward, CURRENCY)})
+
+
+
+ {formatVisualAmount(order.expectedMonthlyReward, order.tokenInfo.decimals)} {order.tokenInfo.symbol}
+ {' ('}
+ {formatCurrency(order.expectedFiatMonthlyReward, CURRENCY)})
+
+
+ {order.fee}%
+
+
+ {isOrder ? (
+
+ You will own{' '}
+
+ {order.numValidators} Ethereum validator{order.numValidators === 1 ? '' : 's'}
+
+
+ ) : (
+ {order.numValidators}
+ )}
+
+ {formatDurationFromSeconds(order.estimatedEntryTime)}
+ Approx. every 5 days after 4 days from activation
+
+ {!isOrder && (
+
+
+
+ )}
+
+ {isOrder && (
+
+ Earn ETH rewards with dedicated validators. Rewards must be withdrawn manually, and you can request a
+ withdrawal at any time.
+
+ )}
+
+
+ )
+}
+
+export default StakingConfirmationTxDeposit
diff --git a/src/features/stake/components/StakingConfirmationTx/Exit.tsx b/src/features/stake/components/StakingConfirmationTx/Exit.tsx
new file mode 100644
index 0000000000..4c68d07073
--- /dev/null
+++ b/src/features/stake/components/StakingConfirmationTx/Exit.tsx
@@ -0,0 +1,48 @@
+import { Typography, Stack, Alert } from '@mui/material'
+import FieldsGrid from '@/components/tx/FieldsGrid'
+import type { StakingTxExitInfo } from '@safe-global/safe-gateway-typescript-sdk'
+import { formatDurationFromSeconds } from '@/utils/formatters'
+import { type NativeStakingValidatorsExitConfirmationView } from '@safe-global/safe-gateway-typescript-sdk/dist/types/decoded-data'
+import ConfirmationOrderHeader from '@/components/tx/ConfirmationOrder/ConfirmationOrderHeader'
+
+type StakingOrderConfirmationViewProps = {
+ order: NativeStakingValidatorsExitConfirmationView | StakingTxExitInfo
+}
+
+const StakingConfirmationTxExit = ({ order }: StakingOrderConfirmationViewProps) => {
+ const withdrawIn = formatDurationFromSeconds(order.estimatedExitTime + order.estimatedWithdrawalTime, [
+ 'days',
+ 'hours',
+ ])
+
+ return (
+
+
+
+ Up to {withdrawIn}
+
+
+ The selected amount and any rewards will be withdrawn from Dedicated Staking for ETH after the validator exit.
+
+
+
+ This transaction is a withdrawal request. After it's executed, you'll need to complete a separate
+ withdrawal transaction.
+
+
+ )
+}
+
+export default StakingConfirmationTxExit
diff --git a/src/features/stake/components/StakingConfirmationTx/index.tsx b/src/features/stake/components/StakingConfirmationTx/index.tsx
new file mode 100644
index 0000000000..407546f03a
--- /dev/null
+++ b/src/features/stake/components/StakingConfirmationTx/index.tsx
@@ -0,0 +1,25 @@
+import type { AnyStakingConfirmationView } from '@safe-global/safe-gateway-typescript-sdk'
+import { ConfirmationViewTypes, type StakingTxInfo } from '@safe-global/safe-gateway-typescript-sdk'
+import StakingConfirmationTxDeposit from '@/features/stake/components/StakingConfirmationTx/Deposit'
+import StakingConfirmationTxExit from '@/features/stake/components/StakingConfirmationTx/Exit'
+
+type StakingOrderConfirmationViewProps = {
+ order: AnyStakingConfirmationView | StakingTxInfo
+}
+
+const StrakingConfirmationTx = ({ order }: StakingOrderConfirmationViewProps) => {
+ const isDeposit = order.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_DEPOSIT
+ const isExit = order.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_VALIDATORS_EXIT
+
+ if (isDeposit) {
+ return
+ }
+
+ if (isExit) {
+ return
+ }
+
+ return null
+}
+
+export default StrakingConfirmationTx
diff --git a/src/features/stake/components/StakingStatus/index.tsx b/src/features/stake/components/StakingStatus/index.tsx
new file mode 100644
index 0000000000..d8ae9ab853
--- /dev/null
+++ b/src/features/stake/components/StakingStatus/index.tsx
@@ -0,0 +1,77 @@
+import { NativeStakingExitStatus, NativeStakingStatus } from '@safe-global/safe-gateway-typescript-sdk'
+import { SvgIcon } from '@mui/material'
+import CheckIcon from '@/public/images/common/circle-check.svg'
+import ClockIcon from '@/public/images/common/clock.svg'
+import SignatureIcon from '@/public/images/common/document_signature.svg'
+import TxStatusChip, { type TxStatusChipProps } from '@/components/transactions/TxStatusChip'
+
+const ColorIcons: Record<
+ NativeStakingStatus | NativeStakingExitStatus,
+ | {
+ color: TxStatusChipProps['color']
+ icon?: React.ComponentType
+ text: string
+ }
+ | undefined
+> = {
+ [NativeStakingStatus.AWAITING_ENTRY]: {
+ color: 'info',
+ icon: ClockIcon,
+ text: 'Activating',
+ },
+ [NativeStakingStatus.REQUESTED_EXIT]: {
+ color: 'info',
+ icon: ClockIcon,
+ text: 'Requested exit',
+ },
+ [NativeStakingStatus.SIGNATURE_NEEDED]: {
+ color: 'warning',
+ icon: SignatureIcon,
+ text: 'Signature needed',
+ },
+ [NativeStakingStatus.AWAITING_EXECUTION]: {
+ color: 'warning',
+ icon: ClockIcon,
+ text: 'Awaiting execution',
+ },
+ [NativeStakingStatus.VALIDATION_STARTED]: {
+ color: 'success',
+ icon: CheckIcon,
+ text: 'Validation started',
+ },
+ [NativeStakingStatus.WITHDRAWN]: {
+ color: 'success',
+ icon: CheckIcon,
+ text: 'Withdrawn',
+ },
+ [NativeStakingExitStatus.READY_TO_WITHDRAW]: {
+ color: 'success',
+ icon: CheckIcon,
+ text: 'Ready to withdraw',
+ },
+ [NativeStakingExitStatus.REQUEST_PENDING]: {
+ color: 'info',
+ icon: ClockIcon,
+ text: 'Request pending',
+ },
+ [NativeStakingStatus.UNKNOWN]: undefined,
+}
+
+const capitalizedStatus = (status: string) =>
+ status
+ .toLowerCase()
+ .replace(/_/g, ' ')
+ .replace(/^\w/g, (l) => l.toUpperCase())
+
+const StakingStatus = ({ status }: { status: NativeStakingStatus | NativeStakingExitStatus }) => {
+ const config = ColorIcons[status]
+
+ return (
+
+ {config?.icon && }
+ {config?.text || capitalizedStatus(status)}
+
+ )
+}
+
+export default StakingStatus
diff --git a/src/features/stake/components/StakingTxDepositDetails/index.tsx b/src/features/stake/components/StakingTxDepositDetails/index.tsx
new file mode 100644
index 0000000000..1a3e3c9d0a
--- /dev/null
+++ b/src/features/stake/components/StakingTxDepositDetails/index.tsx
@@ -0,0 +1,21 @@
+import { Box } from '@mui/material'
+import type { StakingTxDepositInfo, TransactionData } from '@safe-global/safe-gateway-typescript-sdk'
+import FieldsGrid from '@/components/tx/FieldsGrid'
+import SendAmountBlock from '@/components/tx-flow/flows/TokenTransfer/SendAmountBlock'
+import StakingConfirmationTxDeposit from '@/features/stake/components/StakingConfirmationTx/Deposit'
+
+const StakingTxDepositDetails = ({ info, txData }: { info: StakingTxDepositInfo; txData?: TransactionData }) => {
+ return (
+
+ {txData && (
+
+ )}
+
+ {info.annualNrr.toFixed(3)}%
+
+
+
+ )
+}
+
+export default StakingTxDepositDetails
diff --git a/src/features/stake/components/StakingTxDepositInfo/index.tsx b/src/features/stake/components/StakingTxDepositInfo/index.tsx
new file mode 100644
index 0000000000..d7d4bf150d
--- /dev/null
+++ b/src/features/stake/components/StakingTxDepositInfo/index.tsx
@@ -0,0 +1,8 @@
+import type { StakingTxInfo } from '@safe-global/safe-gateway-typescript-sdk'
+import { camelCaseToSpaces } from '@/utils/formatters'
+
+export const StakingTxDepositInfo = ({ info }: { info: StakingTxInfo }) => {
+ return <>{camelCaseToSpaces(info.type).toLowerCase()}>
+}
+
+export default StakingTxDepositInfo
diff --git a/src/features/stake/components/StakingTxExitDetails/index.tsx b/src/features/stake/components/StakingTxExitDetails/index.tsx
new file mode 100644
index 0000000000..31e4839cd4
--- /dev/null
+++ b/src/features/stake/components/StakingTxExitDetails/index.tsx
@@ -0,0 +1,34 @@
+import { Box } from '@mui/material'
+import type { StakingTxExitInfo, TransactionData } from '@safe-global/safe-gateway-typescript-sdk'
+import FieldsGrid from '@/components/tx/FieldsGrid'
+import TokenAmount from '@/components/common/TokenAmount'
+import StakingStatus from '@/features/stake/components/StakingStatus'
+import { formatDurationFromSeconds } from '@/utils/formatters'
+
+const StakingTxExitDetails = ({ info }: { info: StakingTxExitInfo; txData?: TransactionData }) => {
+ const withdrawIn = formatDurationFromSeconds(info.estimatedExitTime + info.estimatedWithdrawalTime, ['days', 'hours'])
+ return (
+
+
+
+
+
+
+ {info.numValidators} Validator{info.numValidators > 1 ? 's' : ''}
+
+
+ Up to {withdrawIn}
+
+
+
+
+
+ )
+}
+
+export default StakingTxExitDetails
diff --git a/src/features/stake/components/StakingTxExitInfo/index.tsx b/src/features/stake/components/StakingTxExitInfo/index.tsx
new file mode 100644
index 0000000000..60fa8ca9e0
--- /dev/null
+++ b/src/features/stake/components/StakingTxExitInfo/index.tsx
@@ -0,0 +1,17 @@
+import type { StakingTxInfo } from '@safe-global/safe-gateway-typescript-sdk'
+import TokenAmount from '@/components/common/TokenAmount'
+
+const StakingTxExitInfo = ({ info }: { info: StakingTxInfo }) => {
+ return (
+ <>
+
+ >
+ )
+}
+
+export default StakingTxExitInfo
diff --git a/src/features/stake/components/StakingWidget/index.tsx b/src/features/stake/components/StakingWidget/index.tsx
new file mode 100644
index 0000000000..cc76afbed4
--- /dev/null
+++ b/src/features/stake/components/StakingWidget/index.tsx
@@ -0,0 +1,35 @@
+import { useMemo } from 'react'
+import { useDarkMode } from '@/hooks/useDarkMode'
+import AppFrame from '@/components/safe-apps/AppFrame'
+import { getEmptySafeApp } from '@/components/safe-apps/utils'
+
+const widgetAppData = {
+ url: 'https://safe.widget.testnet.kiln.fi/earn',
+ name: 'Stake',
+ iconUrl: '/images/common/stake.svg',
+ chainIds: ['17000', '11155111', '1', '42161', '137', '56', '8453', '10'],
+}
+
+const StakingWidget = () => {
+ const isDarkMode = useDarkMode()
+
+ const appData = useMemo(
+ () => ({
+ ...getEmptySafeApp(),
+ ...widgetAppData,
+ url: widgetAppData.url + `?theme=${isDarkMode ? 'dark' : 'light'}`,
+ }),
+ [isDarkMode],
+ )
+
+ return (
+
+ )
+}
+
+export default StakingWidget
diff --git a/src/features/stake/constants.ts b/src/features/stake/constants.ts
new file mode 100644
index 0000000000..59b8a35621
--- /dev/null
+++ b/src/features/stake/constants.ts
@@ -0,0 +1 @@
+export const STAKE_TITLE = 'Stake'
diff --git a/src/features/stake/helpers/utils.ts b/src/features/stake/helpers/utils.ts
new file mode 100644
index 0000000000..69d5693554
--- /dev/null
+++ b/src/features/stake/helpers/utils.ts
@@ -0,0 +1,17 @@
+import { id } from 'ethers'
+import type { BaseTransaction } from '@safe-global/safe-apps-sdk'
+
+const WITHDRAW_SIGHASH = id('requestValidatorsExit(bytes)').slice(0, 10)
+
+export const getStakeTitle = (txs: BaseTransaction[] | undefined) => {
+ const hashToLabel = {
+ [WITHDRAW_SIGHASH]: 'Withdraw request',
+ }
+
+ const stakeTitle = txs
+ ?.map((tx) => hashToLabel[tx.data.slice(0, 10)])
+ .filter(Boolean)
+ .join(' and ')
+
+ return stakeTitle
+}
diff --git a/src/features/stake/useStakeConsent.ts b/src/features/stake/useStakeConsent.ts
new file mode 100644
index 0000000000..4566126551
--- /dev/null
+++ b/src/features/stake/useStakeConsent.ts
@@ -0,0 +1,28 @@
+import { localItem } from '@/services/local-storage/local'
+import { useCallback, useEffect, useState } from 'react'
+
+const STAKE_CONSENT_STORAGE_KEY = 'stakeDisclaimerAcceptedV1'
+const stakeConsentStorage = localItem(STAKE_CONSENT_STORAGE_KEY)
+
+const useStakeConsent = (): {
+ isConsentAccepted: boolean | undefined
+ onAccept: () => void
+} => {
+ const [isConsentAccepted, setIsConsentAccepted] = useState()
+
+ const onAccept = useCallback(() => {
+ setIsConsentAccepted(true)
+ stakeConsentStorage.set(true)
+ }, [setIsConsentAccepted])
+
+ useEffect(() => {
+ setIsConsentAccepted(stakeConsentStorage.get() || false)
+ }, [setIsConsentAccepted])
+
+ return {
+ isConsentAccepted,
+ onAccept,
+ }
+}
+
+export default useStakeConsent
diff --git a/src/features/swap/components/StatusLabel/index.tsx b/src/features/swap/components/StatusLabel/index.tsx
index e8a186714b..67910f4f2a 100644
--- a/src/features/swap/components/StatusLabel/index.tsx
+++ b/src/features/swap/components/StatusLabel/index.tsx
@@ -1,4 +1,4 @@
-import { Chip as MuiChip, SvgIcon } from '@mui/material'
+import { SvgIcon } from '@mui/material'
import type { OrderStatuses } from '@safe-global/safe-gateway-typescript-sdk'
import type { ReactElement } from 'react'
import CheckIcon from '@/public/images/common/circle-check.svg'
@@ -6,6 +6,7 @@ import ClockIcon from '@/public/images/common/clock.svg'
import BlockIcon from '@/public/images/common/block.svg'
import SignatureIcon from '@/public/images/common/document_signature.svg'
import CircleIPartialFillcon from '@/public/images/common/circle-partial-fill.svg'
+import TxStatusChip, { type TxStatusChipProps } from '@/components/transactions/TxStatusChip'
type CustomOrderStatuses = OrderStatuses | 'partiallyFilled'
type Props = {
@@ -14,72 +15,51 @@ type Props = {
type StatusProps = {
label: string
- color: string
- backgroundColor: string
- iconColor: string
- icon: any
+ color: TxStatusChipProps['color']
+ icon: React.ComponentType
}
const statusMap: Record = {
presignaturePending: {
label: 'Execution needed',
- color: 'warning.main',
- backgroundColor: 'warning.background',
- iconColor: 'warning.main',
+ color: 'warning',
icon: SignatureIcon,
},
fulfilled: {
label: 'Filled',
- color: 'success.dark',
- backgroundColor: 'secondary.background',
- iconColor: 'success.dark',
+ color: 'success',
icon: CheckIcon,
},
open: {
label: 'Open',
- color: 'warning.main',
- backgroundColor: 'warning.background',
- iconColor: 'warning.main',
+ color: 'warning',
icon: ClockIcon,
},
cancelled: {
label: 'Cancelled',
- color: 'error.main',
- backgroundColor: 'error.background',
- iconColor: 'error.main',
+ color: 'error',
icon: BlockIcon,
},
expired: {
label: 'Expired',
- color: 'primary.light',
- backgroundColor: 'background.main',
- iconColor: 'border.main',
+ color: 'primary',
icon: ClockIcon,
},
partiallyFilled: {
label: 'Partially filled',
- color: 'success.dark',
- backgroundColor: 'secondary.background',
- iconColor: 'success.dark',
+ color: 'success',
icon: CircleIPartialFillcon,
},
}
export const StatusLabel = (props: Props): ReactElement => {
const { status } = props
- const { label, color, icon, iconColor, backgroundColor } = statusMap[status]
+ const { label, color, icon } = statusMap[status]
return (
- }
- />
+
+
+ {label}
+
)
}
diff --git a/src/features/swap/components/SwapOrderConfirmationView/OrderFeeConfirmationView.tsx b/src/features/swap/components/SwapOrderConfirmationView/OrderFeeConfirmationView.tsx
index 4cc8020a89..8fcf7d3db9 100644
--- a/src/features/swap/components/SwapOrderConfirmationView/OrderFeeConfirmationView.tsx
+++ b/src/features/swap/components/SwapOrderConfirmationView/OrderFeeConfirmationView.tsx
@@ -1,11 +1,15 @@
-import type { OrderConfirmationView } from '@safe-global/safe-gateway-typescript-sdk'
+import type { SwapOrderConfirmationView, TwapOrderConfirmationView } from '@safe-global/safe-gateway-typescript-sdk'
import { getOrderFeeBps } from '@/features/swap/helpers/utils'
import { DataRow } from '@/components/common/Table/DataRow'
import { HelpCenterArticle } from '@/config/constants'
import { HelpIconTooltip } from '@/features/swap/components/HelpIconTooltip'
import MUILink from '@mui/material/Link'
-export const OrderFeeConfirmationView = ({ order }: { order: Pick }) => {
+export const OrderFeeConfirmationView = ({
+ order,
+}: {
+ order: Pick
+}) => {
const bps = getOrderFeeBps(order)
if (Number(bps) === 0) {
diff --git a/src/features/swap/components/SwapOrderConfirmationView/index.tsx b/src/features/swap/components/SwapOrderConfirmationView/index.tsx
index 8c34512b69..2c986286b5 100644
--- a/src/features/swap/components/SwapOrderConfirmationView/index.tsx
+++ b/src/features/swap/components/SwapOrderConfirmationView/index.tsx
@@ -6,9 +6,8 @@ import { DataTable } from '@/components/common/Table/DataTable'
import { compareAsc } from 'date-fns'
import { Alert, Typography } from '@mui/material'
import { formatAmount } from '@/utils/formatNumber'
-import { formatVisualAmount } from '@/utils/formatters'
import { getLimitPrice, getOrderClass, getSlippageInPercent } from '@/features/swap/helpers/utils'
-import type { OrderConfirmationView } from '@safe-global/safe-gateway-typescript-sdk'
+import type { AnySwapOrderConfirmationView } from '@safe-global/safe-gateway-typescript-sdk'
import { StartTimeValue } from '@safe-global/safe-gateway-typescript-sdk'
import { ConfirmationViewTypes } from '@safe-global/safe-gateway-typescript-sdk'
import SwapTokens from '@/features/swap/components/SwapTokens'
@@ -20,13 +19,15 @@ import { PartDuration } from '@/features/swap/components/SwapOrder/rows/PartDura
import { PartSellAmount } from '@/features/swap/components/SwapOrder/rows/PartSellAmount'
import { PartBuyAmount } from '@/features/swap/components/SwapOrder/rows/PartBuyAmount'
import { OrderFeeConfirmationView } from '@/features/swap/components/SwapOrderConfirmationView/OrderFeeConfirmationView'
+import { isSettingTwapFallbackHandler } from '@/features/swap/helpers/utils'
+import { TwapFallbackHandlerWarning } from '@/features/swap/components/TwapFallbackHandlerWarning'
type SwapOrderProps = {
- order: OrderConfirmationView
+ order: AnySwapOrderConfirmationView
settlementContract: string
}
-export const SwapOrderConfirmationView = ({ order, settlementContract }: SwapOrderProps): ReactElement => {
+export const SwapOrderConfirmation = ({ order, settlementContract }: SwapOrderProps): ReactElement => {
const { owner, kind, validUntil, sellToken, buyToken, sellAmount, buyAmount, explorerUrl, receiver } = order
const isTwapOrder = order.type === ConfirmationViewTypes.COW_SWAP_TWAP_ORDER
@@ -38,25 +39,26 @@ export const SwapOrderConfirmationView = ({ order, settlementContract }: SwapOrd
const slippage = getSlippageInPercent(order)
const isSellOrder = kind === 'sell'
+ const isChangingFallbackHandler = isSettingTwapFallbackHandler(order)
return (
-
+ <>
+ {isChangingFallbackHandler && }
+
,
@@ -143,8 +145,8 @@ export const SwapOrderConfirmationView = ({ order, settlementContract }: SwapOrd
/>
)}
-
+ >
)
}
-export default SwapOrderConfirmationView
+export default SwapOrderConfirmation
diff --git a/src/features/swap/components/SwapTokens/index.stories.tsx b/src/features/swap/components/SwapTokens/index.stories.tsx
index 7f5e9b29db..06d9b077a4 100644
--- a/src/features/swap/components/SwapTokens/index.stories.tsx
+++ b/src/features/swap/components/SwapTokens/index.stories.tsx
@@ -28,16 +28,22 @@ export const Default: Story = {
first: {
value: '100',
label: 'Sell',
- logoUri:
- 'https://safe-transaction-assets.staging.5afe.dev/tokens/logos/0x0625aFB445C3B6B7B929342a04A22599fd5dBB59.png',
- tokenSymbol: 'COW',
+ tokenInfo: {
+ decimals: 18,
+ logoUri:
+ 'https://safe-transaction-assets.staging.5afe.dev/tokens/logos/0x0625aFB445C3B6B7B929342a04A22599fd5dBB59.png',
+ symbol: 'COW',
+ },
},
second: {
value: '86',
label: 'For at least',
- logoUri:
- 'https://safe-transaction-assets.staging.5afe.dev/tokens/logos/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984.png',
- tokenSymbol: 'UNI',
+ tokenInfo: {
+ decimals: 18,
+ logoUri:
+ 'https://safe-transaction-assets.staging.5afe.dev/tokens/logos/0x1f9840a85d5aF5bf1D1762F925BDADdC4201F984.png',
+ symbol: 'UNI',
+ },
},
},
}
diff --git a/src/features/swap/components/SwapTokens/index.tsx b/src/features/swap/components/SwapTokens/index.tsx
index d42d876498..15d02327a7 100644
--- a/src/features/swap/components/SwapTokens/index.tsx
+++ b/src/features/swap/components/SwapTokens/index.tsx
@@ -1,53 +1,7 @@
-import type { ReactElement } from 'react'
-import TokenIcon from '@/components/common/TokenIcon'
-import { SvgIcon, Typography } from '@mui/material'
-import Stack from '@mui/material/Stack'
-import css from './styles.module.css'
-import EastRoundedIcon from '@mui/icons-material/EastRounded'
+import ConfirmationOrderHeader, { type InfoBlock } from '@/components/tx/ConfirmationOrder/ConfirmationOrderHeader'
-const SwapToken = ({
- value,
- tokenSymbol,
- label,
- logoUri,
-}: {
- value: string
- tokenSymbol: string
- label?: string
- logoUri?: string
-}): ReactElement => {
- return (
-
-
-
-
- {label}
-
-
- {value} {tokenSymbol}
-
-
-
- )
-}
-
-type SwapToken = {
- value: string
- tokenSymbol: string
- label: string
- logoUri: string
-}
-
-const SwapTokens = ({ first, second }: { first: SwapToken; second: SwapToken }) => {
- return (
-
- )
+const SwapTokens = ({ first, second }: { first: InfoBlock; second: InfoBlock }) => {
+ return
}
export default SwapTokens
diff --git a/src/features/swap/components/SwapTokens/styles.module.css b/src/features/swap/components/SwapTokens/styles.module.css
deleted file mode 100644
index 5dd2ad6751..0000000000
--- a/src/features/swap/components/SwapTokens/styles.module.css
+++ /dev/null
@@ -1,32 +0,0 @@
-.container {
- display: flex;
- gap: var(--space-1);
- position: relative;
-}
-
-.swapToken {
- display: inline-flex;
- align-items: center;
- flex-wrap: wrap;
- gap: var(--space-2);
- color: var(--color-text-primary);
- background: var(--color-background-main);
- padding: var(--space-2) var(--space-3);
- border-radius: 6px;
- flex: 1;
-}
-
-.icon {
- display: flex;
- align-items: center;
- justify-content: center;
- background: var(--color-background-paper);
- border-radius: 50%;
- position: absolute;
- left: 50%;
- top: 50%;
- transform: translate(-50%, -50%);
- width: 40px;
- height: 40px;
- padding: var(--space-1);
-}
diff --git a/src/features/swap/components/TwapFallbackHandlerWarning/index.tsx b/src/features/swap/components/TwapFallbackHandlerWarning/index.tsx
index 470bb515b4..7c9234a3c7 100644
--- a/src/features/swap/components/TwapFallbackHandlerWarning/index.tsx
+++ b/src/features/swap/components/TwapFallbackHandlerWarning/index.tsx
@@ -1,15 +1,17 @@
-import { Alert, Box, SvgIcon } from '@mui/material'
+import { Alert, SvgIcon } from '@mui/material'
import InfoOutlinedIcon from '@/public/images/notifications/info.svg'
export const TwapFallbackHandlerWarning = () => {
return (
-
- }>
- Enable TWAPs and submit order.
- {` `}
- To enable TWAP orders you need to set a custom fallback handler. This software is developed by CoW Swap and Safe
- will not be responsible for any possible issues with it.
-
-
+ }
+ sx={{ mb: 1 }}
+ >
+ Enable TWAPs and submit order.
+ {` `}
+ To enable TWAP orders you need to set a custom fallback handler. This software is developed by CoW Swap and Safe
+ will not be responsible for any possible issues with it.
+
)
}
diff --git a/src/features/swap/index.tsx b/src/features/swap/index.tsx
index 10f5a34fa8..b2ed794996 100644
--- a/src/features/swap/index.tsx
+++ b/src/features/swap/index.tsx
@@ -3,7 +3,7 @@ import { type CowSwapWidgetParams, TradeType } from '@cowprotocol/widget-lib'
import type { OnTradeParamsPayload } from '@cowprotocol/events'
import { type CowEventListeners, CowEvents } from '@cowprotocol/events'
import { type MutableRefObject, useEffect, useMemo, useRef, useState } from 'react'
-import { Box, Container, Grid, useTheme } from '@mui/material'
+import { Box, useTheme } from '@mui/material'
import {
SafeAppAccessPolicyTypes,
type SafeAppData,
@@ -20,14 +20,13 @@ import useWallet from '@/hooks/wallets/useWallet'
import BlockedAddress from '@/components/common/BlockedAddress'
import useSwapConsent from './useSwapConsent'
import Disclaimer from '@/components/common/Disclaimer'
-import LegalDisclaimerContent from '@/features/swap/components/LegalDisclaimer'
+import WidgetDisclaimer from '@/components/common/WidgetDisclaimer'
import { selectSwapParams, setSwapParams, type SwapState } from './store/swapParamsSlice'
import { setSwapOrder } from '@/store/swapOrderSlice'
import useChainId from '@/hooks/useChainId'
import { type BaseTransaction } from '@safe-global/safe-apps-sdk'
import { APPROVAL_SIGNATURE_HASH } from '@/components/tx/ApprovalEditor/utils/approvals'
import { id } from 'ethers'
-import useIsSwapFeatureEnabled from './hooks/useIsSwapFeatureEnabled'
import {
LIMIT_ORDER_TITLE,
SWAP_TITLE,
@@ -81,7 +80,6 @@ const SwapWidget = ({ sell }: Params) => {
const darkMode = useDarkMode()
const chainId = useChainId()
const dispatch = useAppDispatch()
- const isSwapFeatureEnabled = useIsSwapFeatureEnabled()
const swapParams = useAppSelector(selectSwapParams)
const { safeAddress, safeLoading } = useSafeInfo()
const [recipientAddress, setRecipientAddress] = useState('')
@@ -300,16 +298,13 @@ const SwapWidget = ({ sell }: Params) => {
}
if (!isConsentAccepted) {
- return } onAccept={onAccept} buttonText="Continue" />
- }
-
- if (!isSwapFeatureEnabled) {
return (
-
-
- Swaps are not supported on this chain
-
-
+ }
+ onAccept={onAccept}
+ buttonText="Continue"
+ />
)
}
diff --git a/src/hooks/__tests__/useDecodeTx.test.ts b/src/hooks/__tests__/useDecodeTx.test.ts
index f8c7fd7912..99889dc11f 100644
--- a/src/hooks/__tests__/useDecodeTx.test.ts
+++ b/src/hooks/__tests__/useDecodeTx.test.ts
@@ -83,13 +83,14 @@ describe('useDecodeTx', () => {
const safeTx = createMockSafeTransaction({
data: '0x1234567890abcdef', // non-empty data
to: faker.finance.ethereumAddress(),
+ value: '1000000',
})
const { result } = renderHook(() => useDecodeTx(safeTx))
await waitFor(async () => {
expect(getConfirmationView).toHaveBeenCalledTimes(1)
- expect(getConfirmationView).toHaveBeenCalledWith('5', '0x789', '0x1234567890abcdef', safeTx.data.to)
+ expect(getConfirmationView).toHaveBeenCalledWith('5', '0x789', '0x1234567890abcdef', safeTx.data.to, '1000000')
})
})
diff --git a/src/hooks/useChains.ts b/src/hooks/useChains.ts
index 669c99865a..c04e848e01 100644
--- a/src/hooks/useChains.ts
+++ b/src/hooks/useChains.ts
@@ -37,7 +37,7 @@ export const useCurrentChain = (): ChainInfo | undefined => {
* @param feature name of the feature to check for
* @returns `true`, if the feature is enabled on the current chain. Otherwise `false`
*/
-export const useHasFeature = (feature: FEATURES): boolean => {
+export const useHasFeature = (feature: FEATURES): boolean | undefined => {
const currentChain = useCurrentChain()
- return !!currentChain && hasFeature(currentChain, feature)
+ return currentChain ? hasFeature(currentChain, feature) : undefined
}
diff --git a/src/hooks/useDecodeTx.ts b/src/hooks/useDecodeTx.ts
index 72d9b57040..25d7c5cc07 100644
--- a/src/hooks/useDecodeTx.ts
+++ b/src/hooks/useDecodeTx.ts
@@ -1,10 +1,5 @@
import { type SafeTransaction } from '@safe-global/safe-core-sdk-types'
-import {
- getConfirmationView,
- type BaselineConfirmationView,
- type OrderConfirmationView,
- type DecodedDataResponse,
-} from '@safe-global/safe-gateway-typescript-sdk'
+import { getConfirmationView, type AnyConfirmationView } from '@safe-global/safe-gateway-typescript-sdk'
import { getNativeTransferData } from '@/services/tx/tokenTransferParams'
import { isEmptyHexData } from '@/utils/hex'
import type { AsyncResult } from './useAsync'
@@ -12,30 +7,27 @@ import useAsync from './useAsync'
import useChainId from './useChainId'
import useSafeAddress from '@/hooks/useSafeAddress'
-const useDecodeTx = (
- tx?: SafeTransaction,
-): AsyncResult => {
+const useDecodeTx = (tx?: SafeTransaction): AsyncResult => {
const chainId = useChainId()
const safeAddress = useSafeAddress()
- const encodedData = tx?.data.data
- const isEmptyData = !!encodedData && isEmptyHexData(encodedData)
- const isRejection = isEmptyData && tx?.data.value === '0'
+ const { to, value, data } = tx?.data || {}
- const [data, error, loading] = useAsync<
- DecodedDataResponse | BaselineConfirmationView | OrderConfirmationView | undefined
- >(
+ return useAsync(
() => {
- if (!encodedData || isEmptyData) {
- const nativeTransfer = isEmptyData && !isRejection ? getNativeTransferData(tx?.data) : undefined
+ if (to === undefined || value === undefined) return
+
+ const isEmptyData = !!data && isEmptyHexData(data)
+ if (!data || isEmptyData) {
+ const isRejection = isEmptyData && value === '0'
+ const nativeTransfer = isEmptyData && !isRejection ? getNativeTransferData({ to, value }) : undefined
return Promise.resolve(nativeTransfer)
}
- return getConfirmationView(chainId, safeAddress, encodedData, tx.data.to)
+
+ return getConfirmationView(chainId, safeAddress, data, to, value)
},
- [chainId, encodedData, isEmptyData, tx?.data, isRejection, safeAddress],
+ [chainId, safeAddress, to, value, data],
false,
)
-
- return [data, error, loading]
}
export default useDecodeTx
diff --git a/src/hooks/useTransactionType.tsx b/src/hooks/useTransactionType.tsx
index 8b891ce61a..7b33dedd08 100644
--- a/src/hooks/useTransactionType.tsx
+++ b/src/hooks/useTransactionType.tsx
@@ -88,6 +88,18 @@ export const getTransactionType = (tx: TransactionSummary, addressBook: AddressB
text: TWAP_ORDER_TITLE,
}
}
+ case TransactionInfoType.NATIVE_STAKING_DEPOSIT: {
+ return {
+ icon: '/images/common/stake.svg',
+ text: 'Stake',
+ }
+ }
+ case TransactionInfoType.NATIVE_STAKING_VALIDATORS_EXIT: {
+ return {
+ icon: '/images/common/stake.svg',
+ text: 'Withdraw request',
+ }
+ }
case TransactionInfoType.CUSTOM: {
if (isMultiSendTxInfo(tx.txInfo) && !tx.safeAppInfo) {
return {
@@ -110,6 +122,12 @@ export const getTransactionType = (tx: TransactionSummary, addressBook: AddressB
}
}
+ return {
+ icon: toAddress?.logoUri || '/images/transactions/custom.svg',
+ text: addressBookName || toAddress?.name || 'Contract interaction',
+ }
+ }
+ default: {
if (tx.safeAppInfo) {
return {
icon: tx.safeAppInfo.logoUri,
@@ -117,12 +135,6 @@ export const getTransactionType = (tx: TransactionSummary, addressBook: AddressB
}
}
- return {
- icon: toAddress?.logoUri || '/images/transactions/custom.svg',
- text: addressBookName || toAddress?.name || 'Contract interaction',
- }
- }
- default: {
return {
icon: '/images/transactions/custom.svg',
text: addressBookName || 'Contract interaction',
diff --git a/src/pages/stake.tsx b/src/pages/stake.tsx
new file mode 100644
index 0000000000..2b629a2676
--- /dev/null
+++ b/src/pages/stake.tsx
@@ -0,0 +1,32 @@
+import type { NextPage } from 'next'
+import Head from 'next/head'
+import dynamic from 'next/dynamic'
+import { Typography } from '@mui/material'
+import { useHasFeature } from '@/hooks/useChains'
+import { FEATURES } from '@/utils/chains'
+
+const LazyStakePage = dynamic(() => import('@/features/stake/components/StakePage'), { ssr: false })
+
+const StakePage: NextPage = () => {
+ const isFeatureEnabled = useHasFeature(FEATURES.STAKING)
+
+ return (
+ <>
+
+ {'Safe{Wallet} – Stake'}
+
+
+ {isFeatureEnabled === true ? (
+
+ ) : isFeatureEnabled === false ? (
+
+
+ Staking is not available on this network.
+
+
+ ) : null}
+ >
+ )
+}
+
+export default StakePage
diff --git a/src/pages/swap.tsx b/src/pages/swap.tsx
index 35c3cf2aba..0a18c061b8 100644
--- a/src/pages/swap.tsx
+++ b/src/pages/swap.tsx
@@ -1,10 +1,10 @@
import type { NextPage } from 'next'
import Head from 'next/head'
import { useRouter } from 'next/router'
-import { GeoblockingContext } from '@/components/common/GeoblockingProvider'
-import { useContext } from 'react'
-import { AppRoutes } from '@/config/routes'
import dynamic from 'next/dynamic'
+import { Typography } from '@mui/material'
+import { useHasFeature } from '@/hooks/useChains'
+import { FEATURES } from '@/utils/chains'
// Cow Swap expects native token addresses to be in the format '0xeeee...eeee'
const adjustEthAddress = (address: string) => {
@@ -16,14 +16,11 @@ const adjustEthAddress = (address: string) => {
}
const SwapWidgetNoSSR = dynamic(() => import('@/features/swap'), { ssr: false })
-const Swap: NextPage = () => {
+
+const SwapPage: NextPage = () => {
const router = useRouter()
- const isBlockedCountry = useContext(GeoblockingContext)
const { token, amount } = router.query
-
- if (isBlockedCountry) {
- router.replace(AppRoutes['403'])
- }
+ const isFeatureEnabled = useHasFeature(FEATURES.NATIVE_SWAPS)
let sell = undefined
if (token && amount) {
@@ -39,11 +36,17 @@ const Swap: NextPage = () => {
{'Safe{Wallet} – Swap'}
-
-
+
+ {isFeatureEnabled === true ? (
+
+ ) : isFeatureEnabled === false ? (
+
+ Swaps are not supported on this network.
+
+ ) : null}
>
)
}
-export default Swap
+export default SwapPage
diff --git a/src/services/tx/extractTxInfo.ts b/src/services/tx/extractTxInfo.ts
index 6fc690beb4..ece76f119f 100644
--- a/src/services/tx/extractTxInfo.ts
+++ b/src/services/tx/extractTxInfo.ts
@@ -61,6 +61,9 @@ const extractTxInfo = (
return txDetails.txData?.value ?? '0'
case 'SwapOrder':
return txDetails.txData?.value ?? '0'
+ case 'NativeStakingDeposit':
+ case 'NativeStakingValidatorsExit':
+ return txDetails.txData?.value ?? '0'
case 'Custom':
return txDetails.txInfo.value
case 'Creation':
@@ -87,6 +90,13 @@ const extractTxInfo = (
throw new Error('Order tx data does not have a `to` field')
}
return orderTo
+ case 'NativeStakingDeposit':
+ case 'NativeStakingValidatorsExit':
+ const stakingTo = txDetails.txData?.to.value
+ if (!stakingTo) {
+ throw new Error('Staking tx data does not have a `to` field')
+ }
+ return stakingTo
case 'Custom':
return txDetails.txInfo.to.value
case 'Creation':
diff --git a/src/services/tx/tokenTransferParams.ts b/src/services/tx/tokenTransferParams.ts
index 00fff7e8f2..e64ee02ba8 100644
--- a/src/services/tx/tokenTransferParams.ts
+++ b/src/services/tx/tokenTransferParams.ts
@@ -1,5 +1,5 @@
import type { MetaTransactionData } from '@safe-global/safe-core-sdk-types'
-import type { DecodedDataResponse } from '@safe-global/safe-gateway-typescript-sdk'
+import { ConfirmationViewTypes, type BaselineConfirmationView } from '@safe-global/safe-gateway-typescript-sdk'
import { safeParseUnits } from '@/utils/formatters'
import { Interface } from 'ethers'
import { sameAddress } from '@/utils/addresses'
@@ -64,19 +64,23 @@ export const createNftTransferParams = (
}
}
-export const getNativeTransferData = (data: MetaTransactionData): DecodedDataResponse => {
+export const getNativeTransferData = ({
+ to,
+ value,
+}: Pick): BaselineConfirmationView => {
return {
+ type: ConfirmationViewTypes.GENERIC,
method: '',
parameters: [
{
name: 'to',
type: 'address',
- value: data.to,
+ value: to,
},
{
name: 'value',
type: 'uint256',
- value: data.value,
+ value,
},
],
}
diff --git a/src/styles/globals.css b/src/styles/globals.css
index 3b324c2692..d9574f20cd 100644
--- a/src/styles/globals.css
+++ b/src/styles/globals.css
@@ -14,10 +14,6 @@ main {
width: 100%;
}
-main.swapWrapper {
- height: calc(100vh - 52px);
-}
-
a {
color: inherit;
text-decoration: none;
diff --git a/src/utils/__tests__/transactions.test.ts b/src/utils/__tests__/transactions.test.ts
index 52c47123ac..2fa9ae7559 100644
--- a/src/utils/__tests__/transactions.test.ts
+++ b/src/utils/__tests__/transactions.test.ts
@@ -82,6 +82,15 @@ describe('transactions', () => {
expect(getTxOrigin(app)).toBe('{"url":"https://test.com","name":"Test name"}')
})
+ it('should return a stringified object with the app name and url with a query param', () => {
+ const app = {
+ url: 'https://test.com/hello?world=1',
+ name: 'Test name',
+ } as SafeAppData
+
+ expect(getTxOrigin(app)).toBe('{"url":"https://test.com/hello","name":"Test name"}')
+ })
+
it('should limit the origin to 200 characters with preference of the URL', () => {
const app = {
url: 'https://test.com/' + 'a'.repeat(160),
diff --git a/src/utils/chains.ts b/src/utils/chains.ts
index 10e8c721d1..0e5179df62 100644
--- a/src/utils/chains.ts
+++ b/src/utils/chains.ts
@@ -34,13 +34,13 @@ export enum FEATURES {
RELAY_NATIVE_SWAPS = 'RELAY_NATIVE_SWAPS',
ZODIAC_ROLES = 'ZODIAC_ROLES',
SAFE_141 = 'SAFE_141',
- STAKE_TEASER = 'STAKE_TEASER',
+ STAKING = 'STAKING',
}
export const FeatureRoutes = {
[AppRoutes.apps.index]: FEATURES.SAFE_APPS,
[AppRoutes.swap]: FEATURES.NATIVE_SWAPS,
- [AppRoutes.stake]: FEATURES.STAKE_TEASER,
+ [AppRoutes.stake]: FEATURES.STAKING,
[AppRoutes.balances.nfts]: FEATURES.ERC721,
[AppRoutes.settings.notifications]: FEATURES.PUSH_NOTIFICATIONS,
}
diff --git a/src/utils/formatters.ts b/src/utils/formatters.ts
index 253549f8b5..60c5fbea41 100644
--- a/src/utils/formatters.ts
+++ b/src/utils/formatters.ts
@@ -1,6 +1,7 @@
import type { BigNumberish } from 'ethers'
import { formatUnits, parseUnits } from 'ethers'
import { formatAmount, formatAmountPrecise } from './formatNumber'
+import { formatDuration, intervalToDuration } from 'date-fns'
const GWEI = 'gwei'
@@ -94,3 +95,11 @@ export const formatError = (error: Error & { reason?: string }): string => {
if (!reason.endsWith('.')) reason += '.'
return ` ${capitalize(reason)}`
}
+
+export const formatDurationFromSeconds = (
+ seconds: number,
+ format: Array<'years' | 'months' | 'days' | 'hours' | 'minutes' | 'seconds'> = ['hours', 'minutes'],
+) => {
+ const duration = intervalToDuration({ start: 0, end: seconds * 1000 })
+ return formatDuration(duration, { format })
+}
diff --git a/src/utils/transaction-guards.ts b/src/utils/transaction-guards.ts
index a92fe19a12..57e8c5e0ef 100644
--- a/src/utils/transaction-guards.ts
+++ b/src/utils/transaction-guards.ts
@@ -6,7 +6,6 @@ import type {
Creation,
Custom,
DateLabel,
- DecodedDataResponse,
DetailedExecutionInfo,
Erc20Transfer,
Erc721Transfer,
@@ -18,8 +17,10 @@ import type {
MultisigExecutionDetails,
MultisigExecutionInfo,
NativeCoinTransfer,
+ NativeStakingDepositConfirmationView,
Order,
- OrderConfirmationView,
+ AnyConfirmationView,
+ AnySwapOrderConfirmationView,
SafeInfo,
SettingsChange,
SwapOrder,
@@ -32,6 +33,9 @@ import type {
TransferInfo,
TwapOrder,
TwapOrderConfirmationView,
+ AnyStakingConfirmationView,
+ StakingTxExitInfo,
+ StakingTxDepositInfo,
} from '@safe-global/safe-gateway-typescript-sdk'
import {
ConfirmationViewTypes,
@@ -48,6 +52,7 @@ import { sameAddress } from '@/utils/addresses'
import type { NamedAddress } from '@/components/new-safe/create/types'
import type { RecoveryQueueItem } from '@/features/recovery/services/recovery-state'
import { ethers } from 'ethers'
+import type { NativeStakingValidatorsExitConfirmationView } from '@safe-global/safe-gateway-typescript-sdk/dist/types/decoded-data'
export const isTxQueued = (value: TransactionStatus): boolean => {
return [TransactionStatus.AWAITING_CONFIRMATIONS, TransactionStatus.AWAITING_EXECUTION].includes(value)
@@ -119,14 +124,17 @@ export const isTwapOrderTxInfo = (value: TransactionInfo): value is TwapOrder =>
return value.type === TransactionInfoType.TWAP_ORDER
}
-export const isConfirmationViewOrder = (
- decodedData: DecodedDataResponse | BaselineConfirmationView | OrderConfirmationView | undefined,
-): decodedData is OrderConfirmationView => {
- return isSwapConfirmationViewOrder(decodedData) || isTwapConfirmationViewOrder(decodedData)
+export const isStakingTxDepositInfo = (value: TransactionInfo): value is StakingTxDepositInfo => {
+ return value.type === TransactionInfoType.NATIVE_STAKING_DEPOSIT
+}
+
+export const isStakingTxExitInfo = (value: TransactionInfo): value is StakingTxExitInfo => {
+ console.log('is staking tx exit info', value, TransactionInfoType.NATIVE_STAKING_VALIDATORS_EXIT)
+ return value.type === TransactionInfoType.NATIVE_STAKING_VALIDATORS_EXIT
}
export const isTwapConfirmationViewOrder = (
- decodedData: DecodedDataResponse | BaselineConfirmationView | OrderConfirmationView | undefined,
+ decodedData: AnyConfirmationView | undefined,
): decodedData is TwapOrderConfirmationView => {
if (decodedData && 'type' in decodedData) {
return decodedData.type === ConfirmationViewTypes.COW_SWAP_TWAP_ORDER
@@ -136,7 +144,7 @@ export const isTwapConfirmationViewOrder = (
}
export const isSwapConfirmationViewOrder = (
- decodedData: DecodedDataResponse | BaselineConfirmationView | OrderConfirmationView | undefined,
+ decodedData: AnyConfirmationView | undefined,
): decodedData is SwapOrderConfirmationView => {
if (decodedData && 'type' in decodedData) {
return decodedData.type === ConfirmationViewTypes.COW_SWAP_ORDER
@@ -145,6 +153,45 @@ export const isSwapConfirmationViewOrder = (
return false
}
+export const isAnySwapConfirmationViewOrder = (
+ decodedData: AnyConfirmationView | undefined,
+): decodedData is AnySwapOrderConfirmationView => {
+ return isSwapConfirmationViewOrder(decodedData) || isTwapConfirmationViewOrder(decodedData)
+}
+
+export const isStakingDepositConfirmationView = (
+ decodedData: AnyConfirmationView | undefined,
+): decodedData is NativeStakingDepositConfirmationView => {
+ if (decodedData && 'type' in decodedData) {
+ return decodedData?.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_DEPOSIT
+ }
+ return false
+}
+
+export const isStakingExitConfirmationView = (
+ decodedData: AnyConfirmationView | undefined,
+): decodedData is NativeStakingValidatorsExitConfirmationView => {
+ if (decodedData && 'type' in decodedData) {
+ return decodedData?.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_VALIDATORS_EXIT
+ }
+ return false
+}
+
+export const isAnyStakingConfirmationView = (
+ decodedData: AnyConfirmationView | undefined,
+): decodedData is AnyStakingConfirmationView => {
+ return isStakingDepositConfirmationView(decodedData) || isStakingExitConfirmationView(decodedData)
+}
+
+export const isGenericConfirmation = (
+ decodedData: AnyConfirmationView | undefined,
+): decodedData is BaselineConfirmationView => {
+ if (decodedData && 'type' in decodedData) {
+ return decodedData.type === ConfirmationViewTypes.GENERIC
+ }
+ return false
+}
+
export const isCancelledSwapOrder = (value: TransactionInfo) => {
return isSwapOrderTxInfo(value) && value.status === 'cancelled'
}
diff --git a/src/utils/transactions.ts b/src/utils/transactions.ts
index a3e151e739..304f5555e1 100644
--- a/src/utils/transactions.ts
+++ b/src/utils/transactions.ts
@@ -34,6 +34,7 @@ import { toBeHex, AbiCoder } from 'ethers'
import { type BaseTransaction } from '@safe-global/safe-apps-sdk'
import { id } from 'ethers'
import { isEmptyHexData } from '@/utils/hex'
+import { getOriginPath } from './url'
export const makeTxFromDetails = (txDetails: TransactionDetails): Transaction => {
const getMissingSigners = ({
@@ -186,7 +187,7 @@ export const getTxOrigin = (app?: Partial): string | undefined => {
try {
// Must include empty string to avoid including the length of `undefined`
const maxUrlLength = MAX_ORIGIN_LENGTH - JSON.stringify({ url: '', name: '' }).length
- const trimmedUrl = url.slice(0, maxUrlLength)
+ const trimmedUrl = getOriginPath(url).slice(0, maxUrlLength)
const maxNameLength = Math.max(0, maxUrlLength - trimmedUrl.length)
const trimmedName = name.slice(0, maxNameLength)
diff --git a/src/utils/url.ts b/src/utils/url.ts
index d0322e4748..a9c5eb19fd 100644
--- a/src/utils/url.ts
+++ b/src/utils/url.ts
@@ -1,8 +1,8 @@
-const trimTrailingSlash = (url: string): string => {
+export const trimTrailingSlash = (url: string): string => {
return url.replace(/\/$/, '')
}
-const isSameUrl = (url1: string, url2: string): boolean => {
+export const isSameUrl = (url1: string, url2: string): boolean => {
return trimTrailingSlash(url1) === trimTrailingSlash(url2)
}
export const prefixedAddressRe = /[a-z0-9-]+\:0x[a-f0-9]{40}/i
@@ -10,11 +10,11 @@ const invalidProtocolRegex = /^(\W*)(javascript|data|vbscript)/im
const ctrlCharactersRegex = /[\u0000-\u001F\u007F-\u009F\u2000-\u200D\uFEFF]/gim
const urlSchemeRegex = /^([^:]+):/gm
const relativeFirstCharacters = ['.', '/']
-const isRelativeUrl = (url: string): boolean => {
+export const isRelativeUrl = (url: string): boolean => {
return relativeFirstCharacters.indexOf(url[0]) > -1
}
-const sanitizeUrl = (url: string): string => {
+export const sanitizeUrl = (url: string): string => {
const sanitizedUrl = url.replace(ctrlCharactersRegex, '').trim()
if (isRelativeUrl(sanitizedUrl)) {
@@ -34,4 +34,12 @@ const sanitizeUrl = (url: string): string => {
return sanitizedUrl
}
-export { trimTrailingSlash, isSameUrl, sanitizeUrl, isRelativeUrl }
+export const getOriginPath = (url: string): string => {
+ try {
+ const { origin, pathname } = new URL(url)
+ return origin + (pathname === '/' ? '' : pathname)
+ } catch (e) {
+ console.error('Error parsing URL', url, e)
+ return url
+ }
+}
diff --git a/yarn.lock b/yarn.lock
index 2039d231b8..2df338f673 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4183,10 +4183,10 @@
dependencies:
semver "^7.6.2"
-"@safe-global/safe-gateway-typescript-sdk@3.22.4-beta.1":
- version "3.22.4-beta.1"
- resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.4-beta.1.tgz#ef8d0506d8c747124fae721a9baf99dda71af189"
- integrity sha512-adxHiSeUc47MqkW7BM50U5xy6144rDEf0jyftzGXrBkG+nv/oL55SZQ/DdAsxyI1Mns02gzawa3Up+MfA8SKCQ==
+"@safe-global/safe-gateway-typescript-sdk@3.22.3-beta.12":
+ version "3.22.3-beta.12"
+ resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.3-beta.12.tgz#2ebc398d6c8c4f27cc68865dbd7e7603add099ae"
+ integrity sha512-BBcyYNa8RDN5tQrYHOp3Bdo3CTo7r6ZB0Nzgce5OI7rKjorgCv0TprVTW8w8YVMXa74wC6uT06udXAB0IDRu8A==
"@safe-global/safe-gateway-typescript-sdk@^3.5.3":
version "3.21.2"
@@ -16694,16 +16694,7 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0":
- version "4.2.3"
- resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
- integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
- dependencies:
- emoji-regex "^8.0.0"
- is-fullwidth-code-point "^3.0.0"
- strip-ansi "^6.0.1"
-
-string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16791,14 +16782,7 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
- version "6.0.1"
- resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
- integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
- dependencies:
- ansi-regex "^5.0.1"
-
-strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1", 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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18482,7 +18466,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18500,15 +18484,6 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
-wrap-ansi@^7.0.0:
- version "7.0.0"
- resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
- integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
- dependencies:
- ansi-styles "^4.0.0"
- string-width "^4.1.0"
- strip-ansi "^6.0.0"
-
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From 50c753cc31d7a952b16088c850eef9d380b90cff Mon Sep 17 00:00:00 2001
From: Michael <30682308+mike10ca@users.noreply.github.com>
Date: Thu, 12 Sep 2024 16:11:14 +0200
Subject: [PATCH 66/81] Tests: Fix regression tests (#4164)
* Fix tests
---
cypress/e2e/pages/create_wallet.pages.js | 3 ++-
cypress/e2e/regression/create_safe_cf.cy.js | 2 +-
cypress/support/utils/wallet.js | 2 +-
src/features/counterfactual/ActivateAccountButton.tsx | 2 +-
4 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/cypress/e2e/pages/create_wallet.pages.js b/cypress/e2e/pages/create_wallet.pages.js
index ce62d6a7a4..1c79e430c6 100644
--- a/cypress/e2e/pages/create_wallet.pages.js
+++ b/cypress/e2e/pages/create_wallet.pages.js
@@ -32,7 +32,7 @@ export const choiceBtn = '[data-testid="choice-btn"]'
const addFundsBtn = '[data-testid="add-funds-btn"]'
const createTxBtn = '[data-testid="create-tx-btn"]'
const qrCodeSwitch = '[data-testid="qr-code-switch"]'
-export const activateAccountBtn = '[data-testid="activate-account-btn"]'
+export const activateAccountBtn = '[data-testid="activate-account-btn-cf"]'
const notificationsSwitch = '[data-testid="notifications-switch"]'
export const addFundsSection = '[data-testid="add-funds-section"]'
export const noTokensAlert = '[data-testid="no-tokens-alert"]'
@@ -50,6 +50,7 @@ export const addSignerStr = 'Add signer'
export const accountRecoveryStr = 'Account recovery'
export const sendTokensStr = 'Send tokens'
const noWalletConnectedMsg = 'No wallet connected'
+export const deployWalletStr = 'about to deploy this Safe Account'
const connectWalletBtn = '[data-testid="connect-wallet-btn"]'
diff --git a/cypress/e2e/regression/create_safe_cf.cy.js b/cypress/e2e/regression/create_safe_cf.cy.js
index 6bdf9a2bed..b4d5754542 100644
--- a/cypress/e2e/regression/create_safe_cf.cy.js
+++ b/cypress/e2e/regression/create_safe_cf.cy.js
@@ -88,7 +88,7 @@ describe('CF Safe regression tests', () => {
owner.waitForConnectionStatus()
createwallet.clickOnCreateTxBtn()
createwallet.clickOnTxType(txOrder[0])
- main.verifyElementsExist([createwallet.activateAccountBtn])
+ cy.contains(createwallet.deployWalletStr)
})
it('Verify "Add another Owner" takes to a tx Add owner', () => {
diff --git a/cypress/support/utils/wallet.js b/cypress/support/utils/wallet.js
index 8daee1aa2d..0187b9b41b 100644
--- a/cypress/support/utils/wallet.js
+++ b/cypress/support/utils/wallet.js
@@ -23,7 +23,7 @@ export function connectSigner(signer) {
function handlePkConnect() {
cy.get('body').then(($body) => {
if ($body.find(pkConnectBtn).length > 0) {
- cy.get(pkInput).find('input').clear().type(signer)
+ cy.get(pkInput).find('input').clear().type(signer, { log: false })
cy.get(pkConnectBtn).click()
}
})
diff --git a/src/features/counterfactual/ActivateAccountButton.tsx b/src/features/counterfactual/ActivateAccountButton.tsx
index d98b890913..7b2c4efa43 100644
--- a/src/features/counterfactual/ActivateAccountButton.tsx
+++ b/src/features/counterfactual/ActivateAccountButton.tsx
@@ -28,7 +28,7 @@ const ActivateAccountButton = () => {
{(isOk) => (
Date: Fri, 13 Sep 2024 10:21:32 +0200
Subject: [PATCH 67/81] Tests: Fix regression cy 2 (#4168)
* Fix regression tests
---
cypress/e2e/regression/create_tx.cy.js | 1 -
cypress/e2e/regression/swaps_history_2.cy.js | 12 ++----------
cypress/e2e/regression/tokens.cy.js | 10 ++++++++--
3 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/cypress/e2e/regression/create_tx.cy.js b/cypress/e2e/regression/create_tx.cy.js
index 5ffc74b51b..ed5ef64c34 100644
--- a/cypress/e2e/regression/create_tx.cy.js
+++ b/cypress/e2e/regression/create_tx.cy.js
@@ -39,7 +39,6 @@ describe('Create transactions tests', () => {
createtx.changeNonce(14)
cy.wait(1000)
createtx.clickOnSignTransactionBtn()
- createtx.waitForProposeRequest()
createtx.clickViewTransaction()
createtx.verifySingleTxPage()
createtx.verifyQueueLabel()
diff --git a/cypress/e2e/regression/swaps_history_2.cy.js b/cypress/e2e/regression/swaps_history_2.cy.js
index 03e113208b..ca71f2d32c 100644
--- a/cypress/e2e/regression/swaps_history_2.cy.js
+++ b/cypress/e2e/regression/swaps_history_2.cy.js
@@ -25,14 +25,7 @@ describe('Swaps history tests 2', () => {
const dai = swaps.createRegex(swapsHistory.forAtLeastFullDai, 'DAI')
const eq = swaps.createRegex(swapsHistory.DAIeqCOW, 'COW')
- create_tx.verifyExpandedDetails([
- swapsHistory.sellFull,
- dai,
- eq,
- swapsHistory.dai,
- swapsHistory.filled,
- swapsHistory.gGpV2,
- ])
+ create_tx.verifyExpandedDetails([swapsHistory.sellFull, dai, eq, swapsHistory.dai, swapsHistory.filled])
})
// TODO: Added to prod
@@ -70,7 +63,6 @@ describe('Swaps history tests 2', () => {
eq,
swapsHistory.cow,
swapsHistory.cancelled,
- swapsHistory.gGpV2,
])
})
@@ -133,7 +125,7 @@ describe('Swaps history tests 2', () => {
swapsHistory.forAtMost,
])
main.verifyValuesDoNotExist(create_tx.transactionItem, [swapsHistory.title, swapsHistory.cow, swapsHistory.dai])
- main.verifyValuesExist(create_tx.transactionItem, [swapsHistory.actionPreSignatureG, swapsHistory.safeAppTitile])
+ main.verifyValuesExist(create_tx.transactionItem, [swapsHistory.actionPreSignatureG, swapsHistory.gGpV2])
},
)
diff --git a/cypress/e2e/regression/tokens.cy.js b/cypress/e2e/regression/tokens.cy.js
index 374d398189..24fbe4c663 100644
--- a/cypress/e2e/regression/tokens.cy.js
+++ b/cypress/e2e/regression/tokens.cy.js
@@ -2,6 +2,7 @@ import * as constants from '../../support/constants'
import * as main from '../pages/main.page'
import * as assets from '../pages/assets.pages'
import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js'
+import * as ls from '../../support/localstorage_data.js'
const ASSET_NAME_COLUMN = 0
const TOKEN_AMOUNT_COLUMN = 1
@@ -17,8 +18,13 @@ describe('Tokens tests', () => {
})
beforeEach(() => {
cy.visit(constants.BALANCE_URL + staticSafes.SEP_STATIC_SAFE_2)
- cy.clearLocalStorage()
- main.acceptCookies()
+ cy.clearLocalStorage().then(() => {
+ main.addToLocalStorage(constants.localStorageKeys.SAFE_v2_cookies_1_1, ls.cookies.acceptedCookies)
+ main.addToLocalStorage(
+ constants.localStorageKeys.SAFE_v2__tokenlist_onboarding,
+ ls.cookies.acceptedTokenListOnboarding,
+ )
+ })
})
// TODO: Added to prod
From c37c7c08a568d472e3cde60211062269715b35f9 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Fri, 13 Sep 2024 15:56:18 +0200
Subject: [PATCH 68/81] Fix: "New" chip positioning (#4170)
---
src/components/common/Chip/index.tsx | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/components/common/Chip/index.tsx b/src/components/common/Chip/index.tsx
index 5cf901d4be..9cabe3c161 100644
--- a/src/components/common/Chip/index.tsx
+++ b/src/components/common/Chip/index.tsx
@@ -13,8 +13,6 @@ export function Chip({ color = 'primary', label = 'New' }: ChipProps) {
sx={{
backgroundColor: `${color}.background`,
color: `${color}.light`,
- position: 'absolute',
- right: 0,
mt: '-2px',
}}
label={
From 3ddc84df637eec679681ea867a1df79ae9a6473f Mon Sep 17 00:00:00 2001
From: Daniel Dimitrov
Date: Fri, 13 Sep 2024 20:24:55 +0200
Subject: [PATCH 69/81] Feat: staking claim [SW-160] (#4167)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
* feat: add claim decoding
* fix: stake deposit tx info should display amount
* fix: label for rewards
.
* fix: use kiln’s production widget url
* fix: use test widget url when on a testchain
---
package.json | 2 +-
.../transactions/TxDetails/TxData/index.tsx | 6 ++++
src/components/transactions/TxInfo/index.tsx | 6 ++++
.../StakingConfirmationTx/Withdraw.tsx | 29 +++++++++++++++++++
.../StakingConfirmationTx/index.tsx | 6 ++++
.../components/StakingTxDepositInfo/index.tsx | 13 +++++++--
.../StakingTxWithdrawDetails/index.tsx | 13 +++++++++
.../StakingTxWithdrawInfo/index.tsx | 17 +++++++++++
.../stake/components/StakingWidget/index.tsx | 19 ++++++++++--
src/features/stake/helpers/utils.ts | 2 ++
src/hooks/useTransactionType.tsx | 6 ++++
src/services/tx/extractTxInfo.ts | 2 ++
src/utils/transaction-guards.ts | 22 ++++++++++++--
yarn.lock | 8 ++---
14 files changed, 139 insertions(+), 12 deletions(-)
create mode 100644 src/features/stake/components/StakingConfirmationTx/Withdraw.tsx
create mode 100644 src/features/stake/components/StakingTxWithdrawDetails/index.tsx
create mode 100644 src/features/stake/components/StakingTxWithdrawInfo/index.tsx
diff --git a/package.json b/package.json
index c7e12fa92f..263bd06694 100644
--- a/package.json
+++ b/package.json
@@ -58,7 +58,7 @@
"@safe-global/protocol-kit": "^4.1.0",
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-deployments": "^1.37.3",
- "@safe-global/safe-gateway-typescript-sdk": "3.22.3-beta.12",
+ "@safe-global/safe-gateway-typescript-sdk": "3.22.3-beta.13",
"@safe-global/safe-modules-deployments": "^1.2.0",
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
diff --git a/src/components/transactions/TxDetails/TxData/index.tsx b/src/components/transactions/TxDetails/TxData/index.tsx
index a197b02818..2026fa11b2 100644
--- a/src/components/transactions/TxDetails/TxData/index.tsx
+++ b/src/components/transactions/TxDetails/TxData/index.tsx
@@ -1,5 +1,6 @@
import SettingsChangeTxInfo from '@/components/transactions/TxDetails/TxData/SettingsChange'
import type { SpendingLimitMethods } from '@/utils/transaction-guards'
+import { isStakingTxWithdrawInfo } from '@/utils/transaction-guards'
import { isStakingTxExitInfo } from '@/utils/transaction-guards'
import {
isCancellationTxInfo,
@@ -22,6 +23,7 @@ import useChainId from '@/hooks/useChainId'
import SwapOrder from '@/features/swap/components/SwapOrder'
import StakingTxDepositDetails from '@/features/stake/components/StakingTxDepositDetails'
import StakingTxExitDetails from '@/features/stake/components/StakingTxExitDetails'
+import StakingTxWithdrawDetails from '@/features/stake/components/StakingTxWithdrawDetails'
const TxData = ({
txDetails,
@@ -48,6 +50,10 @@ const TxData = ({
return
}
+ if (isStakingTxWithdrawInfo(txDetails.txInfo)) {
+ return
+ }
+
if (isTransferTxInfo(txInfo)) {
return
}
diff --git a/src/components/transactions/TxInfo/index.tsx b/src/components/transactions/TxInfo/index.tsx
index f5f12fdf22..7d4675e823 100644
--- a/src/components/transactions/TxInfo/index.tsx
+++ b/src/components/transactions/TxInfo/index.tsx
@@ -21,11 +21,13 @@ import {
isTransferTxInfo,
isStakingTxDepositInfo,
isStakingTxExitInfo,
+ isStakingTxWithdrawInfo,
} from '@/utils/transaction-guards'
import { ellipsis, shortenAddress } from '@/utils/formatters'
import { useCurrentChain } from '@/hooks/useChains'
import { SwapTx } from '@/features/swap/components/SwapTxInfo/SwapTx'
import StakingTxExitInfo from '@/features/stake/components/StakingTxExitInfo'
+import StakingTxWithdrawInfo from '@/features/stake/components/StakingTxWithdrawInfo'
import { Box } from '@mui/material'
import css from './styles.module.css'
import StakingTxDepositInfo from '@/features/stake/components/StakingTxDepositInfo'
@@ -145,6 +147,10 @@ const TxInfo = ({ info, ...rest }: { info: TransactionInfo; omitSign?: boolean;
return
}
+ if (isStakingTxWithdrawInfo(info)) {
+ return
+ }
+
if (isCustomTxInfo(info)) {
return
}
diff --git a/src/features/stake/components/StakingConfirmationTx/Withdraw.tsx b/src/features/stake/components/StakingConfirmationTx/Withdraw.tsx
new file mode 100644
index 0000000000..1616f667da
--- /dev/null
+++ b/src/features/stake/components/StakingConfirmationTx/Withdraw.tsx
@@ -0,0 +1,29 @@
+import { Stack } from '@mui/material'
+import FieldsGrid from '@/components/tx/FieldsGrid'
+import type {
+ NativeStakingWithdrawConfirmationView,
+ StakingTxWithdrawInfo,
+} from '@safe-global/safe-gateway-typescript-sdk'
+import TokenAmount from '@/components/common/TokenAmount'
+
+type StakingOrderConfirmationViewProps = {
+ order: NativeStakingWithdrawConfirmationView | StakingTxWithdrawInfo
+}
+
+const StakingConfirmationTxWithdraw = ({ order }: StakingOrderConfirmationViewProps) => {
+ return (
+
+
+ {' '}
+
+
+
+ )
+}
+
+export default StakingConfirmationTxWithdraw
diff --git a/src/features/stake/components/StakingConfirmationTx/index.tsx b/src/features/stake/components/StakingConfirmationTx/index.tsx
index 407546f03a..c1309fccb4 100644
--- a/src/features/stake/components/StakingConfirmationTx/index.tsx
+++ b/src/features/stake/components/StakingConfirmationTx/index.tsx
@@ -2,6 +2,7 @@ import type { AnyStakingConfirmationView } from '@safe-global/safe-gateway-types
import { ConfirmationViewTypes, type StakingTxInfo } from '@safe-global/safe-gateway-typescript-sdk'
import StakingConfirmationTxDeposit from '@/features/stake/components/StakingConfirmationTx/Deposit'
import StakingConfirmationTxExit from '@/features/stake/components/StakingConfirmationTx/Exit'
+import StakingConfirmationTxWithdraw from '@/features/stake/components/StakingConfirmationTx/Withdraw'
type StakingOrderConfirmationViewProps = {
order: AnyStakingConfirmationView | StakingTxInfo
@@ -10,6 +11,7 @@ type StakingOrderConfirmationViewProps = {
const StrakingConfirmationTx = ({ order }: StakingOrderConfirmationViewProps) => {
const isDeposit = order.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_DEPOSIT
const isExit = order.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_VALIDATORS_EXIT
+ const isWithdraw = order.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_WITHDRAW
if (isDeposit) {
return
@@ -19,6 +21,10 @@ const StrakingConfirmationTx = ({ order }: StakingOrderConfirmationViewProps) =>
return
}
+ if (isWithdraw) {
+ return
+ }
+
return null
}
diff --git a/src/features/stake/components/StakingTxDepositInfo/index.tsx b/src/features/stake/components/StakingTxDepositInfo/index.tsx
index d7d4bf150d..3ac5774bcc 100644
--- a/src/features/stake/components/StakingTxDepositInfo/index.tsx
+++ b/src/features/stake/components/StakingTxDepositInfo/index.tsx
@@ -1,8 +1,17 @@
import type { StakingTxInfo } from '@safe-global/safe-gateway-typescript-sdk'
-import { camelCaseToSpaces } from '@/utils/formatters'
+import TokenAmount from '@/components/common/TokenAmount'
export const StakingTxDepositInfo = ({ info }: { info: StakingTxInfo }) => {
- return <>{camelCaseToSpaces(info.type).toLowerCase()}>
+ return (
+ <>
+
+ >
+ )
}
export default StakingTxDepositInfo
diff --git a/src/features/stake/components/StakingTxWithdrawDetails/index.tsx b/src/features/stake/components/StakingTxWithdrawDetails/index.tsx
new file mode 100644
index 0000000000..78681f19d0
--- /dev/null
+++ b/src/features/stake/components/StakingTxWithdrawDetails/index.tsx
@@ -0,0 +1,13 @@
+import { Box } from '@mui/material'
+import type { StakingTxWithdrawInfo } from '@safe-global/safe-gateway-typescript-sdk'
+import StakingConfirmationTxWithdraw from '@/features/stake/components/StakingConfirmationTx/Withdraw'
+
+const StakingTxWithdrawDetails = ({ info }: { info: StakingTxWithdrawInfo }) => {
+ return (
+
+
+
+ )
+}
+
+export default StakingTxWithdrawDetails
diff --git a/src/features/stake/components/StakingTxWithdrawInfo/index.tsx b/src/features/stake/components/StakingTxWithdrawInfo/index.tsx
new file mode 100644
index 0000000000..19b30b8119
--- /dev/null
+++ b/src/features/stake/components/StakingTxWithdrawInfo/index.tsx
@@ -0,0 +1,17 @@
+import type { StakingTxWithdrawInfo } from '@safe-global/safe-gateway-typescript-sdk'
+import TokenAmount from '@/components/common/TokenAmount'
+
+const StakingTxWithdrawInfo = ({ info }: { info: StakingTxWithdrawInfo }) => {
+ return (
+ <>
+
+ >
+ )
+}
+
+export default StakingTxWithdrawInfo
diff --git a/src/features/stake/components/StakingWidget/index.tsx b/src/features/stake/components/StakingWidget/index.tsx
index cc76afbed4..3330f86b3c 100644
--- a/src/features/stake/components/StakingWidget/index.tsx
+++ b/src/features/stake/components/StakingWidget/index.tsx
@@ -2,9 +2,13 @@ import { useMemo } from 'react'
import { useDarkMode } from '@/hooks/useDarkMode'
import AppFrame from '@/components/safe-apps/AppFrame'
import { getEmptySafeApp } from '@/components/safe-apps/utils'
+import useChainId from '@/hooks/useChainId'
+import useChains from '@/hooks/useChains'
+const WIDGET_PRODUCTION_URL = 'https://safe.widget.kiln.fi/earn'
+const WIDGET_TESTNET_URL = 'https://safe.widget.testnet.kiln.fi/earn'
const widgetAppData = {
- url: 'https://safe.widget.testnet.kiln.fi/earn',
+ url: WIDGET_PRODUCTION_URL,
name: 'Stake',
iconUrl: '/images/common/stake.svg',
chainIds: ['17000', '11155111', '1', '42161', '137', '56', '8453', '10'],
@@ -12,14 +16,23 @@ const widgetAppData = {
const StakingWidget = () => {
const isDarkMode = useDarkMode()
+ let url = widgetAppData.url
+ const currentChainId = useChainId()
+ const { configs } = useChains()
+ const testChains = useMemo(() => configs.filter((chain) => chain.isTestnet), [configs])
+
+ // if currentChainId is in testChains, then set the url to the testnet version
+ if (testChains.some((chain) => chain.chainId === currentChainId)) {
+ url = WIDGET_TESTNET_URL
+ }
const appData = useMemo(
() => ({
...getEmptySafeApp(),
...widgetAppData,
- url: widgetAppData.url + `?theme=${isDarkMode ? 'dark' : 'light'}`,
+ url: url + `?theme=${isDarkMode ? 'dark' : 'light'}`,
}),
- [isDarkMode],
+ [isDarkMode, url],
)
return (
diff --git a/src/features/stake/helpers/utils.ts b/src/features/stake/helpers/utils.ts
index 69d5693554..5eae4b3839 100644
--- a/src/features/stake/helpers/utils.ts
+++ b/src/features/stake/helpers/utils.ts
@@ -2,10 +2,12 @@ import { id } from 'ethers'
import type { BaseTransaction } from '@safe-global/safe-apps-sdk'
const WITHDRAW_SIGHASH = id('requestValidatorsExit(bytes)').slice(0, 10)
+const CLAIM_SIGHASH = id('batchWithdrawCLFee(bytes)').slice(0, 10)
export const getStakeTitle = (txs: BaseTransaction[] | undefined) => {
const hashToLabel = {
[WITHDRAW_SIGHASH]: 'Withdraw request',
+ [CLAIM_SIGHASH]: 'Claim',
}
const stakeTitle = txs
diff --git a/src/hooks/useTransactionType.tsx b/src/hooks/useTransactionType.tsx
index 7b33dedd08..c87da5ef5c 100644
--- a/src/hooks/useTransactionType.tsx
+++ b/src/hooks/useTransactionType.tsx
@@ -100,6 +100,12 @@ export const getTransactionType = (tx: TransactionSummary, addressBook: AddressB
text: 'Withdraw request',
}
}
+ case TransactionInfoType.NATIVE_STAKING_WITHDRAW: {
+ return {
+ icon: '/images/common/stake.svg',
+ text: 'Claim',
+ }
+ }
case TransactionInfoType.CUSTOM: {
if (isMultiSendTxInfo(tx.txInfo) && !tx.safeAppInfo) {
return {
diff --git a/src/services/tx/extractTxInfo.ts b/src/services/tx/extractTxInfo.ts
index ece76f119f..c40e6862de 100644
--- a/src/services/tx/extractTxInfo.ts
+++ b/src/services/tx/extractTxInfo.ts
@@ -63,6 +63,7 @@ const extractTxInfo = (
return txDetails.txData?.value ?? '0'
case 'NativeStakingDeposit':
case 'NativeStakingValidatorsExit':
+ case 'NativeStakingWithdraw':
return txDetails.txData?.value ?? '0'
case 'Custom':
return txDetails.txInfo.value
@@ -92,6 +93,7 @@ const extractTxInfo = (
return orderTo
case 'NativeStakingDeposit':
case 'NativeStakingValidatorsExit':
+ case 'NativeStakingWithdraw':
const stakingTo = txDetails.txData?.to.value
if (!stakingTo) {
throw new Error('Staking tx data does not have a `to` field')
diff --git a/src/utils/transaction-guards.ts b/src/utils/transaction-guards.ts
index 57e8c5e0ef..e0cc9672a7 100644
--- a/src/utils/transaction-guards.ts
+++ b/src/utils/transaction-guards.ts
@@ -36,6 +36,8 @@ import type {
AnyStakingConfirmationView,
StakingTxExitInfo,
StakingTxDepositInfo,
+ StakingTxWithdrawInfo,
+ NativeStakingWithdrawConfirmationView,
} from '@safe-global/safe-gateway-typescript-sdk'
import {
ConfirmationViewTypes,
@@ -129,10 +131,13 @@ export const isStakingTxDepositInfo = (value: TransactionInfo): value is Staking
}
export const isStakingTxExitInfo = (value: TransactionInfo): value is StakingTxExitInfo => {
- console.log('is staking tx exit info', value, TransactionInfoType.NATIVE_STAKING_VALIDATORS_EXIT)
return value.type === TransactionInfoType.NATIVE_STAKING_VALIDATORS_EXIT
}
+export const isStakingTxWithdrawInfo = (value: TransactionInfo): value is StakingTxWithdrawInfo => {
+ return value.type === TransactionInfoType.NATIVE_STAKING_WITHDRAW
+}
+
export const isTwapConfirmationViewOrder = (
decodedData: AnyConfirmationView | undefined,
): decodedData is TwapOrderConfirmationView => {
@@ -177,10 +182,23 @@ export const isStakingExitConfirmationView = (
return false
}
+export const isStakingWithdrawConfirmationView = (
+ decodedData: AnyConfirmationView | undefined,
+): decodedData is NativeStakingWithdrawConfirmationView => {
+ if (decodedData && 'type' in decodedData) {
+ return decodedData?.type === ConfirmationViewTypes.KILN_NATIVE_STAKING_WITHDRAW
+ }
+ return false
+}
+
export const isAnyStakingConfirmationView = (
decodedData: AnyConfirmationView | undefined,
): decodedData is AnyStakingConfirmationView => {
- return isStakingDepositConfirmationView(decodedData) || isStakingExitConfirmationView(decodedData)
+ return (
+ isStakingDepositConfirmationView(decodedData) ||
+ isStakingExitConfirmationView(decodedData) ||
+ isStakingWithdrawConfirmationView(decodedData)
+ )
}
export const isGenericConfirmation = (
diff --git a/yarn.lock b/yarn.lock
index 2df338f673..02fd3ccbfc 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4183,10 +4183,10 @@
dependencies:
semver "^7.6.2"
-"@safe-global/safe-gateway-typescript-sdk@3.22.3-beta.12":
- version "3.22.3-beta.12"
- resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.3-beta.12.tgz#2ebc398d6c8c4f27cc68865dbd7e7603add099ae"
- integrity sha512-BBcyYNa8RDN5tQrYHOp3Bdo3CTo7r6ZB0Nzgce5OI7rKjorgCv0TprVTW8w8YVMXa74wC6uT06udXAB0IDRu8A==
+"@safe-global/safe-gateway-typescript-sdk@3.22.3-beta.13":
+ version "3.22.3-beta.13"
+ resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.22.3-beta.13.tgz#e6feaf93b16788ec6237c7f73f0d57f8514dde0c"
+ integrity sha512-VAoil8BbAsG14cDFG/sSFmCBIGQpJbyQeI7O7LFkPGwCVOFhHhE7SiurDiSkw13QLLxnIqB/Hq6jse+wa7Ny9g==
"@safe-global/safe-gateway-typescript-sdk@^3.5.3":
version "3.21.2"
From 5403bc090db81c176f8867f2c22381f1f98a55f3 Mon Sep 17 00:00:00 2001
From: Michael <30682308+mike10ca@users.noreply.github.com>
Date: Sun, 15 Sep 2024 21:42:57 +0200
Subject: [PATCH 70/81] Tests: Add google events tests (#4169)
* Add google events tests
---
cypress/e2e/pages/create_tx.pages.js | 5 ++
cypress/e2e/pages/main.page.js | 9 ++
cypress/e2e/pages/navigation.page.js | 4 +-
cypress/e2e/regression/add_owner.cy.js | 41 +++++++++
cypress/e2e/regression/create_safe_cf.cy.js | 4 +-
cypress/e2e/regression/recovery.cy.js | 2 +-
cypress/e2e/regression/replace_owner.cy.js | 17 +++-
cypress/e2e/regression/swaps.cy.js | 59 +++++++++++++
.../e2e/safe-apps/drain_account.spec.cy.js | 2 +-
cypress/e2e/safe-apps/tx-builder.spec.cy.js | 84 ++++++++++++++++---
cypress/e2e/smoke/create_safe_cf.cy.js | 21 ++++-
cypress/fixtures/safes/static.json | 3 +-
cypress/support/utils/gtag.js | 72 ++++++++++++++++
cypress/support/utils/wallet.js | 2 +-
14 files changed, 300 insertions(+), 25 deletions(-)
create mode 100644 cypress/support/utils/gtag.js
diff --git a/cypress/e2e/pages/create_tx.pages.js b/cypress/e2e/pages/create_tx.pages.js
index a5ef52a0b5..315211344b 100644
--- a/cypress/e2e/pages/create_tx.pages.js
+++ b/cypress/e2e/pages/create_tx.pages.js
@@ -59,6 +59,7 @@ const editBtnStr = 'Edit'
const executionParamsStr = 'Execution parameters'
const noLaterStr = 'No, later'
const signBtnStr = 'Sign'
+const confirmBtnStr = 'Confirm'
const expandAllBtnStr = 'Expand all'
const collapseAllBtnStr = 'Collapse all'
export const messageNestedStr = `"nestedString": "Test message 3 off-chain"`
@@ -504,6 +505,10 @@ export function clickOnSignTransactionBtn() {
cy.get('button').contains(signBtnStr).click()
}
+export function clickOnConfirmTransactionBtn() {
+ cy.get('button').contains(confirmBtnStr).click()
+}
+
export function waitForProposeRequest() {
cy.intercept('POST', constants.proposeEndpoint).as('ProposeTx')
cy.wait('@ProposeTx')
diff --git a/cypress/e2e/pages/main.page.js b/cypress/e2e/pages/main.page.js
index 5643720ef9..18c4a546aa 100644
--- a/cypress/e2e/pages/main.page.js
+++ b/cypress/e2e/pages/main.page.js
@@ -333,3 +333,12 @@ export function getIframeBody(iframe) {
export const checkButtonByTextExists = (buttonText) => {
cy.get('button').contains(buttonText).should('exist')
}
+
+export function getAddedSafeAddressFromLocalStorage(chainId, index) {
+ return cy.window().then((win) => {
+ const addedSafes = win.localStorage.getItem(constants.localStorageKeys.SAFE_v2__addedSafes)
+ const addedSafesObj = JSON.parse(addedSafes)
+ const safeAddress = Object.keys(addedSafesObj[chainId])[index]
+ return safeAddress
+ })
+}
diff --git a/cypress/e2e/pages/navigation.page.js b/cypress/e2e/pages/navigation.page.js
index 5e5bd0b41c..18971fd50c 100644
--- a/cypress/e2e/pages/navigation.page.js
+++ b/cypress/e2e/pages/navigation.page.js
@@ -16,8 +16,8 @@ export function clickOnSideNavigation(option) {
cy.get(option).should('exist').click()
}
-export function clickOnModalCloseBtn() {
- cy.get(modalCloseIcon).eq(0).trigger('click')
+export function clickOnModalCloseBtn(index) {
+ cy.get(modalCloseIcon).eq(index).trigger('click')
}
export function clickOnNewTxBtn() {
diff --git a/cypress/e2e/regression/add_owner.cy.js b/cypress/e2e/regression/add_owner.cy.js
index 617eb43903..a544c76021 100644
--- a/cypress/e2e/regression/add_owner.cy.js
+++ b/cypress/e2e/regression/add_owner.cy.js
@@ -4,10 +4,14 @@ import * as owner from '../pages/owners.pages'
import * as addressBook from '../pages/address_book.page'
import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js'
import * as wallet from '../../support/utils/wallet.js'
+import * as createTx from '../pages/create_tx.pages.js'
+import * as navigation from '../pages/navigation.page'
+import { getEvents, events, checkDataLayerEvents } from '../../support/utils/gtag.js'
let staticSafes = []
const walletCredentials = JSON.parse(Cypress.env('CYPRESS_WALLET_CREDENTIALS'))
const signer = walletCredentials.OWNER_4_PRIVATE_KEY
+const signer2 = walletCredentials.OWNER_1_PRIVATE_KEY
describe('Add Owners tests', () => {
before(async () => {
@@ -60,4 +64,41 @@ describe('Add Owners tests', () => {
owner.clickOnNextBtn()
owner.verifyConfirmTransactionWindowDisplayed()
})
+
+ it('Verify creation, confirmation and deletion of Add owner tx. GA tx_confirm', () => {
+ const tx_confirmed = [
+ {
+ eventLabel: events.txConfirmedAddOwner.eventLabel,
+ eventCategory: events.txConfirmedAddOwner.category,
+ eventType: events.txConfirmedAddOwner.eventType,
+ safeAddress: staticSafes.SEP_STATIC_SAFE_24.slice(6),
+ },
+ ]
+ cy.visit(constants.setupUrl + staticSafes.SEP_STATIC_SAFE_24)
+ wallet.connectSigner(signer2)
+ owner.waitForConnectionStatus()
+ owner.openAddOwnerWindow()
+ owner.typeOwnerAddress(constants.SEPOLIA_OWNER_2)
+ createTx.changeNonce(2)
+ owner.clickOnNextBtn()
+ createTx.clickOnSignTransactionBtn()
+ createTx.clickViewTransaction()
+
+ navigation.clickOnWalletExpandMoreIcon()
+ navigation.clickOnDisconnectBtn()
+ wallet.connectSigner(signer)
+
+ createTx.clickOnConfirmTransactionBtn()
+ createTx.clickOnNoLaterOption()
+ createTx.clickOnSignTransactionBtn()
+
+ navigation.clickOnWalletExpandMoreIcon()
+ navigation.clickOnDisconnectBtn()
+ wallet.connectSigner(signer2)
+
+ createTx.deleteTx()
+
+ getEvents()
+ checkDataLayerEvents(tx_confirmed)
+ })
})
diff --git a/cypress/e2e/regression/create_safe_cf.cy.js b/cypress/e2e/regression/create_safe_cf.cy.js
index b4d5754542..0ab54755d1 100644
--- a/cypress/e2e/regression/create_safe_cf.cy.js
+++ b/cypress/e2e/regression/create_safe_cf.cy.js
@@ -40,10 +40,10 @@ describe('CF Safe regression tests', () => {
owner.waitForConnectionStatus()
createwallet.clickOnAddFundsBtn()
main.verifyElementsIsVisible([createwallet.qrCode])
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(0)
createwallet.clickOnCreateTxBtn()
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(0)
})
it('Verify "0 out of 2 step completed" is shown in the dashboard', () => {
diff --git a/cypress/e2e/regression/recovery.cy.js b/cypress/e2e/regression/recovery.cy.js
index 8b5d9260d1..37d585cc90 100644
--- a/cypress/e2e/regression/recovery.cy.js
+++ b/cypress/e2e/regression/recovery.cy.js
@@ -147,7 +147,7 @@ describe('Recovery regression tests', { defaultCommandTimeout: 50000 }, () => {
recovery.enterRecovererAddress(constants.SEPOLIA_OWNER_2)
recovery.agreeToTerms()
recovery.clickOnNextBtn()
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(0)
recovery.getSetupRecoveryBtn()
navigation.clickOnWalletExpandMoreIcon()
navigation.clickOnDisconnectBtn()
diff --git a/cypress/e2e/regression/replace_owner.cy.js b/cypress/e2e/regression/replace_owner.cy.js
index ec4e6cd875..e996ba60e2 100644
--- a/cypress/e2e/regression/replace_owner.cy.js
+++ b/cypress/e2e/regression/replace_owner.cy.js
@@ -5,10 +5,12 @@ import * as createTx from '../pages/create_tx.pages.js'
import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js'
import * as wallet from '../../support/utils/wallet.js'
import * as ls from '../../support/localstorage_data.js'
+import { getEvents, events, checkDataLayerEvents } from '../../support/utils/gtag.js'
let staticSafes = []
const walletCredentials = JSON.parse(Cypress.env('CYPRESS_WALLET_CREDENTIALS'))
const signer = walletCredentials.OWNER_4_PRIVATE_KEY
+const signer2 = walletCredentials.OWNER_1_PRIVATE_KEY
const ownerName = 'Replacement Signer Name'
@@ -76,8 +78,16 @@ describe('Replace Owners tests', () => {
owner.verifyErrorMsgInvalidAddress(constants.addressBookErrrMsg.alreadyAdded)
})
- // TODO: Flaky. Fix ProposeTx request
- it.skip("Verify 'Replace' tx is created", () => {
+ it("Verify 'Replace' tx is created. GA tx_created", () => {
+ const tx_created = [
+ {
+ eventLabel: events.txCreatedSwapOwner.eventLabel,
+ eventCategory: events.txCreatedSwapOwner.category,
+ eventAction: events.txCreatedSwapOwner.action,
+ event: events.txCreatedSwapOwner.eventName,
+ safeAddress: staticSafes.SEP_STATIC_SAFE_4.slice(6),
+ },
+ ]
cy.visit(constants.setupUrl + staticSafes.SEP_STATIC_SAFE_4)
wallet.connectSigner(signer)
owner.waitForConnectionStatus()
@@ -88,8 +98,9 @@ describe('Replace Owners tests', () => {
createTx.changeNonce(2)
owner.clickOnNextBtn()
createTx.clickOnSignTransactionBtn()
- createTx.waitForProposeRequest()
createTx.clickViewTransaction()
createTx.verifyReplacedSigner(ownerName)
+ getEvents()
+ checkDataLayerEvents(tx_created)
})
})
diff --git a/cypress/e2e/regression/swaps.cy.js b/cypress/e2e/regression/swaps.cy.js
index 35883ea1ab..bad6689cbe 100644
--- a/cypress/e2e/regression/swaps.cy.js
+++ b/cypress/e2e/regression/swaps.cy.js
@@ -7,10 +7,14 @@ import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js'
import * as owner from '../pages/owners.pages'
import * as wallet from '../../support/utils/wallet.js'
import * as swaps_data from '../../fixtures/swaps_data.json'
+import * as navigation from '../pages/navigation.page'
+import { getEvents, events, checkDataLayerEvents } from '../../support/utils/gtag.js'
const walletCredentials = JSON.parse(Cypress.env('CYPRESS_WALLET_CREDENTIALS'))
const signer = walletCredentials.OWNER_4_PRIVATE_KEY
const signer2 = walletCredentials.OWNER_3_WALLET_ADDRESS
+const signer3 = walletCredentials.OWNER_1_PRIVATE_KEY
+
let staticSafes = []
let iframeSelector
@@ -197,4 +201,59 @@ describe('Swaps tests', () => {
})
},
)
+
+ it(
+ 'Verify an order can be created, signed by second signer and deleted. GA tx_confirm, tx_created',
+ { defaultCommandTimeout: 30000 },
+ () => {
+ const tx_created = [
+ {
+ eventLabel: events.txCreatedSwap.eventLabel,
+ eventCategory: events.txCreatedSwap.category,
+ eventType: events.txCreatedSwap.eventType,
+ safeAddress: staticSafes.SEP_STATIC_SAFE_1.slice(6),
+ },
+ ]
+ const tx_confirmed = [
+ {
+ eventLabel: events.txConfirmedSwap.eventLabel,
+ eventCategory: events.txConfirmedSwap.category,
+ eventType: events.txConfirmedSwap.eventType,
+ safeAddress: staticSafes.SEP_STATIC_SAFE_1.slice(6),
+ },
+ ]
+ swaps.acceptLegalDisclaimer()
+ cy.wait(4000)
+ main.getIframeBody(iframeSelector).within(() => {
+ swaps.clickOnSettingsBtn()
+ swaps.setSlippage('0.30')
+ swaps.setExpiry('2')
+ swaps.clickOnSettingsBtn()
+ swaps.selectInputCurrency(swaps.swapTokens.cow)
+ swaps.checkTokenBalance(staticSafes.SEP_STATIC_SAFE_1.substring(4), swaps.swapTokens.cow)
+ swaps.setInputValue(100)
+ swaps.selectOutputCurrency(swaps.swapTokens.dai)
+ swaps.clickOnExceeFeeChkbox()
+ swaps.clickOnSwapBtn()
+ swaps.clickOnSwapBtn()
+ })
+ create_tx.changeNonce(22)
+ create_tx.clickOnSignTransactionBtn()
+ create_tx.clickViewTransaction()
+ navigation.clickOnWalletExpandMoreIcon()
+ navigation.clickOnDisconnectBtn()
+ wallet.connectSigner(signer3)
+ create_tx.clickOnConfirmTransactionBtn()
+ create_tx.clickOnNoLaterOption()
+ create_tx.clickOnSignTransactionBtn()
+ navigation.clickOnWalletExpandMoreIcon()
+ navigation.clickOnDisconnectBtn()
+ wallet.connectSigner(signer)
+ create_tx.deleteTx()
+
+ getEvents()
+ checkDataLayerEvents(tx_created)
+ checkDataLayerEvents(tx_confirmed)
+ },
+ )
})
diff --git a/cypress/e2e/safe-apps/drain_account.spec.cy.js b/cypress/e2e/safe-apps/drain_account.spec.cy.js
index ecc989d2c1..293fc78a26 100644
--- a/cypress/e2e/safe-apps/drain_account.spec.cy.js
+++ b/cypress/e2e/safe-apps/drain_account.spec.cy.js
@@ -69,7 +69,7 @@ describe('Drain Account tests', () => {
getBody().findByLabelText(safeapps.recipientStr).type(safeAppSafes.SEP_SAFEAPP_SAFE_2)
getBody().findAllByText(safeapps.transferEverythingStr).click()
})
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(1)
cy.enter(iframeSelector).then((getBody) => {
getBody().findAllByText(safeapps.transferEverythingStr).should('be.visible')
})
diff --git a/cypress/e2e/safe-apps/tx-builder.spec.cy.js b/cypress/e2e/safe-apps/tx-builder.spec.cy.js
index 3f4ae3822e..5ced7d6123 100644
--- a/cypress/e2e/safe-apps/tx-builder.spec.cy.js
+++ b/cypress/e2e/safe-apps/tx-builder.spec.cy.js
@@ -1,35 +1,44 @@
import 'cypress-file-upload'
import * as constants from '../../support/constants'
-import * as main from '../pages/main.page'
import * as safeapps from '../pages/safeapps.pages'
import * as createtx from '../../e2e/pages/create_tx.pages'
import * as navigation from '../pages/navigation.page'
import { getSafes, CATEGORIES } from '../../support/safes/safesHandler.js'
import * as ls from '../../support/localstorage_data.js'
+import { getEvents, events, checkDataLayerEvents } from '../../support/utils/gtag.js'
+import * as wallet from '../../support/utils/wallet.js'
let safeAppSafes = []
let iframeSelector
-describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
+const walletCredentials = JSON.parse(Cypress.env('CYPRESS_WALLET_CREDENTIALS'))
+const signer = walletCredentials.OWNER_4_PRIVATE_KEY
+const signer2 = walletCredentials.OWNER_1_PRIVATE_KEY
+
+describe.skip('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
before(async () => {
safeAppSafes = await getSafes(CATEGORIES.safeapps)
- cy.clearLocalStorage().then(() => {
- main.addToLocalStorage(constants.localStorageKeys.SAFE_v2_cookies_1_1, ls.cookies.acceptedCookies)
- main.addToLocalStorage(
+ })
+
+ beforeEach(() => {
+ cy.clearLocalStorage()
+ cy.clearCookies()
+ cy.window().then((win) => {
+ win.localStorage.setItem(constants.localStorageKeys.SAFE_v2_cookies_1_1, ls.cookies.acceptedCookies)
+ win.localStorage.setItem(
constants.localStorageKeys.SAFE_v2__SafeApps__infoModal,
ls.appPermissions(constants.safeTestAppurl).infoModalAccepted,
)
})
- })
- beforeEach(() => {
const appUrl = constants.TX_Builder_url
iframeSelector = `iframe[id="iframe-${appUrl}"]`
const visitUrl = `/apps/open?safe=${safeAppSafes.SEP_SAFEAPP_SAFE_1}&appUrl=${encodeURIComponent(appUrl)}`
cy.visit(visitUrl)
})
- it('Verify a simple batch can be created', () => {
+ // TODO: Check if we still need this test as we now create complete flow of creating, signing and deleting a tx
+ it.skip('Verify a simple batch can be created', () => {
cy.enter(iframeSelector).then((getBody) => {
getBody().findByLabelText(safeapps.enterAddressStr).type(constants.SAFE_APP_ADDRESS)
getBody().find(safeapps.contractMethodIndex).parent().click()
@@ -74,7 +83,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
})
cy.get('h4').contains(safeapps.transactionBuilderStr).should('be.visible')
cy.findAllByText(safeapps.testBooleanValue).should('have.length', 6)
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(0)
cy.enter(iframeSelector).then((getBody) => {
getBody().findAllByText(constants.SEPOLIA_CONTRACT_SHORT).should('have.length', 3)
getBody().findAllByText(safeapps.testBooleanValue).should('have.length', 3)
@@ -115,7 +124,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
getBody().findByText(safeapps.sendBatchStr).click()
})
cy.get('h4').contains(safeapps.transactionBuilderStr).should('be.visible')
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(0)
cy.enter(iframeSelector).then((getBody) => {
getBody().findAllByText(constants.SEPOLIA_RECIPIENT_ADDR_SHORT).should('have.length', 1)
getBody().findAllByText(safeapps.testFallback).should('have.length', 1)
@@ -137,7 +146,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
getBody().findByText(safeapps.sendBatchStr).click()
})
cy.get('h4').contains(safeapps.transactionBuilderStr).should('be.visible')
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(0)
cy.enter(iframeSelector).then((getBody) => {
getBody().findAllByText(constants.SEPOLIA_CONTRACT_SHORT).should('have.length', 1)
getBody().findAllByText(safeapps.customData).should('have.length', 1)
@@ -193,7 +202,7 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
})
cy.get('h4').contains(safeapps.transactionBuilderStr).should('be.visible')
cy.findAllByText(safeapps.testAddressValueStr).should('have.length', 4)
- navigation.clickOnModalCloseBtn()
+ navigation.clickOnModalCloseBtn(0)
cy.enter(iframeSelector).then((getBody) => {
getBody().findAllByText(constants.SEPOLIA_CONTRACT_SHORT).should('have.length', 2)
getBody().findAllByText(safeapps.testAddressValueStr).should('have.length', 2)
@@ -304,4 +313,55 @@ describe('Transaction Builder tests', { defaultCommandTimeout: 20000 }, () => {
getBody().findByText(safeapps.failedStr).should('be.visible')
})
})
+
+ // TODO: Fix visibility element
+ it.skip('Verify a simple batch can be created, signed by second signer and deleted. GA tx_confirm, tx_created', () => {
+ const tx_created = [
+ {
+ eventLabel: events.txCreatedTxBuilder.eventLabel,
+ eventCategory: events.txCreatedTxBuilder.category,
+ eventType: events.txCreatedTxBuilder.eventType,
+ event: events.txCreatedTxBuilder.event,
+ safeAddress: safeAppSafes.SEP_SAFEAPP_SAFE_1.slice(6),
+ },
+ ]
+ const tx_confirmed = [
+ {
+ eventLabel: events.txConfirmedTxBuilder.eventLabel,
+ eventCategory: events.txConfirmedTxBuilder.category,
+ eventType: events.txConfirmedTxBuilder.eventType,
+ safeAddress: safeAppSafes.SEP_SAFEAPP_SAFE_1.slice(6),
+ },
+ ]
+ wallet.connectSigner(signer)
+ cy.enter(iframeSelector).then((getBody) => {
+ getBody().findByLabelText(safeapps.enterAddressStr).type(constants.SAFE_APP_ADDRESS)
+ getBody().find(safeapps.contractMethodIndex).parent().click()
+ getBody().findByRole('option', { name: safeapps.testAddressValue2 }).click()
+ getBody().findByLabelText(safeapps.newAddressValueStr).type(safeAppSafes.SEP_SAFEAPP_SAFE_2)
+ getBody().findByText(safeapps.addTransactionStr).click()
+ getBody().findAllByText(constants.SEPOLIA_CONTRACT_SHORT).should('have.length', 1)
+ getBody().findByText(safeapps.testAddressValueStr).should('exist')
+ getBody().findByText(safeapps.createBatchStr).click()
+ getBody().findByText(safeapps.sendBatchStr).click()
+ })
+
+ createtx.clickOnSignTransactionBtn()
+ createtx.clickViewTransaction()
+ navigation.clickOnWalletExpandMoreIcon()
+ navigation.clickOnDisconnectBtn()
+ wallet.connectSigner(signer2)
+
+ createtx.clickOnConfirmTransactionBtn()
+ createtx.clickOnNoLaterOption()
+ createtx.clickOnSignTransactionBtn()
+ navigation.clickOnWalletExpandMoreIcon()
+ navigation.clickOnDisconnectBtn()
+ wallet.connectSigner(signer)
+ createtx.deleteTx()
+ createtx.verifyNumberOfTransactions(0)
+ getEvents()
+ checkDataLayerEvents(tx_created)
+ checkDataLayerEvents(tx_confirmed)
+ })
})
diff --git a/cypress/e2e/smoke/create_safe_cf.cy.js b/cypress/e2e/smoke/create_safe_cf.cy.js
index d7fc4cafa4..346d3ca5d0 100644
--- a/cypress/e2e/smoke/create_safe_cf.cy.js
+++ b/cypress/e2e/smoke/create_safe_cf.cy.js
@@ -3,6 +3,7 @@ import * as main from '../pages/main.page'
import * as createwallet from '../pages/create_wallet.pages'
import * as owner from '../pages/owners.pages'
import * as wallet from '../../support/utils/wallet.js'
+import { getEvents, events, checkDataLayerEvents } from '../../support/utils/gtag.js'
const walletCredentials = JSON.parse(Cypress.env('CYPRESS_WALLET_CREDENTIALS'))
// DO NOT use OWNER_2_PRIVATE_KEY for safe creation. Used for CF safes.
@@ -13,8 +14,10 @@ describe('[SMOKE] CF Safe creation tests', () => {
cy.visit(constants.welcomeUrl + '?chain=sep')
cy.clearLocalStorage()
main.acceptCookies()
+ getEvents()
})
- it('[SMOKE] CF creation happy path', () => {
+
+ it('[SMOKE] CF creation happy path. GA safe_created', () => {
wallet.connectSigner(signer)
owner.waitForConnectionStatus()
createwallet.clickOnContinueWithWalletBtn()
@@ -23,6 +26,20 @@ describe('[SMOKE] CF Safe creation tests', () => {
createwallet.clickOnNextBtn()
createwallet.selectPayLaterOption()
createwallet.clickOnReviewStepNextBtn()
- createwallet.verifyCFSafeCreated()
+ cy.wait(1000)
+ main.getAddedSafeAddressFromLocalStorage(constants.networkKeys.sepolia, 0).then((address) => {
+ const safe_created = [
+ {
+ eventLabel: events.safeCreatedCF.eventLabel,
+ eventCategory: events.safeCreatedCF.category,
+ eventAction: events.safeCreatedCF.action,
+ eventType: events.safeCreatedCF.eventType,
+ event: events.safeCreatedCF.eventName,
+ safeAddress: address.slice(2),
+ },
+ ]
+ checkDataLayerEvents(safe_created)
+ createwallet.verifyCFSafeCreated()
+ })
})
})
diff --git a/cypress/fixtures/safes/static.json b/cypress/fixtures/safes/static.json
index ab7c42513c..83fb7ab50f 100644
--- a/cypress/fixtures/safes/static.json
+++ b/cypress/fixtures/safes/static.json
@@ -23,5 +23,6 @@
"AVAX_STATIC_SAFE_20": "avax:0x480e5A3E90a3fF4a16AECCB5d638fAba96a15c28",
"LINEA_STATIC_SAFE_21": "linea:0x95934e67299E0B3DD277907acABB512802f3536E",
"ZKSYNC_STATIC_SAFE_22": "zksync:0x49136c0270c5682FFbb38Cb29Ecf0563b2E1F9f6",
- "SEP_STATIC_SAFE_23": "sep:0x589d862CE2d519d5A862066bB923da0564c3D2EA"
+ "SEP_STATIC_SAFE_23": "sep:0x589d862CE2d519d5A862066bB923da0564c3D2EA",
+ "SEP_STATIC_SAFE_24": "sep:0x49DC5764961DA4864DC5469f16BC68a0F765f2F2"
}
diff --git a/cypress/support/utils/gtag.js b/cypress/support/utils/gtag.js
new file mode 100644
index 0000000000..fe6e9fd07d
--- /dev/null
+++ b/cypress/support/utils/gtag.js
@@ -0,0 +1,72 @@
+export function getEvents() {
+ cy.window().then((win) => {
+ cy.wrap(win.dataLayer).as('dataLayer')
+ })
+}
+
+export const checkDataLayerEvents = (expectedEvents) => {
+ cy.get('@dataLayer').should((dataLayer) => {
+ expectedEvents.forEach((expectedEvent) => {
+ const eventExists = dataLayer.some((event) => {
+ return Object.keys(expectedEvent).every((key) => {
+ return event[key] === expectedEvent[key]
+ })
+ })
+ expect(eventExists, `Expected event matching fields: ${JSON.stringify(expectedEvent)} not found`).to.be.true
+ })
+ })
+}
+
+export const events = {
+ safeCreatedCF: {
+ category: 'create-safe',
+ action: 'Created Safe',
+ eventName: 'safe_created',
+ eventLabel: 'counterfactual',
+ eventType: 'safe_created',
+ },
+
+ txCreatedSwapOwner: {
+ category: 'transactions',
+ action: 'Create transaction',
+ eventName: 'tx_created',
+ eventLabel: 'owner_swap',
+ },
+
+ txConfirmedAddOwner: {
+ category: 'transactions',
+ action: 'Confirm transaction',
+ eventLabel: 'owner_add',
+ eventType: 'tx_confirmed',
+ event: 'tx_confirmed',
+ },
+ txCreatedSwap: {
+ category: 'transactions',
+ action: 'Confirm transaction',
+ eventLabel: 'native_swap',
+ eventType: 'tx_created',
+ },
+
+ txConfirmedSwap: {
+ category: 'transactions',
+ action: 'Confirm transaction',
+ eventLabel: 'native_swap',
+ eventType: 'tx_confirmed',
+ },
+
+ txCreatedTxBuilder: {
+ category: 'transactions',
+ action: 'Confirm transaction',
+ eventLabel: 'https://safe-apps.dev.5afe.dev/tx-builder',
+ eventType: 'tx_created',
+ event: 'tx_created',
+ },
+
+ txConfirmedTxBuilder: {
+ category: 'transactions',
+ action: 'Confirm transaction',
+ eventLabel: 'https://safe-apps.dev.5afe.dev/tx-builder',
+ eventType: 'tx_confirmed',
+ event: 'tx_confirmed',
+ },
+}
diff --git a/cypress/support/utils/wallet.js b/cypress/support/utils/wallet.js
index 0187b9b41b..957b229f10 100644
--- a/cypress/support/utils/wallet.js
+++ b/cypress/support/utils/wallet.js
@@ -23,7 +23,7 @@ export function connectSigner(signer) {
function handlePkConnect() {
cy.get('body').then(($body) => {
if ($body.find(pkConnectBtn).length > 0) {
- cy.get(pkInput).find('input').clear().type(signer, { log: false })
+ cy.get(pkInput).find('input').clear().type(signer, { log: false, force: true })
cy.get(pkConnectBtn).click()
}
})
From 9b6d8e0cec818de46cbecf960a96686546bb7d6f Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 16 Sep 2024 11:33:54 +0200
Subject: [PATCH 71/81] Chore(deps): Bump semver from 7.6.0 to 7.6.3 (#4175)
Bumps [semver](https://github.com/npm/node-semver) from 7.6.0 to 7.6.3.
- [Release notes](https://github.com/npm/node-semver/releases)
- [Changelog](https://github.com/npm/node-semver/blob/main/CHANGELOG.md)
- [Commits](https://github.com/npm/node-semver/compare/v7.6.0...v7.6.3)
---
updated-dependencies:
- dependency-name: semver
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 46 ++++++++++++++++++++++++++++++++--------------
2 files changed, 33 insertions(+), 15 deletions(-)
diff --git a/package.json b/package.json
index 263bd06694..e4ea5e284f 100644
--- a/package.json
+++ b/package.json
@@ -91,7 +91,7 @@
"react-hook-form": "7.41.1",
"react-papaparse": "^4.0.2",
"react-redux": "^9.1.2",
- "semver": "^7.5.2",
+ "semver": "^7.6.3",
"zodiac-roles-deployments": "^2.2.5"
},
"devDependencies": {
diff --git a/yarn.lock b/yarn.lock
index 02fd3ccbfc..ca44c7d4ce 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -16210,17 +16210,10 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
-semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0:
- version "7.6.0"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
- integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
- dependencies:
- lru-cache "^6.0.0"
-
-semver@^7.6.2:
- version "7.6.2"
- resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13"
- integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==
+semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.3.8, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.2, semver@^7.6.3:
+ version "7.6.3"
+ resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143"
+ integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==
send@0.18.0:
version "0.18.0"
@@ -16694,7 +16687,16 @@ string-length@^4.0.1:
char-regex "^1.0.2"
strip-ansi "^6.0.0"
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+"string-width-cjs@npm:string-width@^4.2.0":
+ version "4.2.3"
+ resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+ integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+ dependencies:
+ emoji-regex "^8.0.0"
+ is-fullwidth-code-point "^3.0.0"
+ strip-ansi "^6.0.1"
+
+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"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -16782,7 +16784,14 @@ stringify-object@^3.3.0:
is-obj "^1.0.1"
is-regexp "^1.0.0"
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+ version "6.0.1"
+ resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+ integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+ dependencies:
+ ansi-regex "^5.0.1"
+
+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"
integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -18466,7 +18475,7 @@ workbox-window@7.0.0:
"@types/trusted-types" "^2.0.2"
workbox-core "7.0.0"
-"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0:
+"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
@@ -18484,6 +18493,15 @@ wrap-ansi@^6.2.0:
string-width "^4.1.0"
strip-ansi "^6.0.0"
+wrap-ansi@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
+ integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==
+ dependencies:
+ ansi-styles "^4.0.0"
+ string-width "^4.1.0"
+ strip-ansi "^6.0.0"
+
wrap-ansi@^8.1.0:
version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
From 06ec6beecd0b13fc225a0cb800e604f1cbc866c5 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 16 Sep 2024 11:35:33 +0200
Subject: [PATCH 72/81] Chore(deps): Bump fuse.js from 6.6.2 to 7.0.0 (#4173)
Bumps [fuse.js](https://github.com/krisk/Fuse) from 6.6.2 to 7.0.0.
- [Release notes](https://github.com/krisk/Fuse/releases)
- [Changelog](https://github.com/krisk/Fuse/blob/main/CHANGELOG.md)
- [Commits](https://github.com/krisk/Fuse/compare/v6.6.2...v7.0.0)
---
updated-dependencies:
- dependency-name: fuse.js
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/package.json b/package.json
index e4ea5e284f..ba2378b361 100644
--- a/package.json
+++ b/package.json
@@ -77,7 +77,7 @@
"ethers": "^6.11.1",
"exponential-backoff": "^3.1.0",
"firebase": "^10.3.1",
- "fuse.js": "^6.6.2",
+ "fuse.js": "^7.0.0",
"idb-keyval": "^6.2.1",
"js-cookie": "^3.0.1",
"lodash": "^4.17.21",
diff --git a/yarn.lock b/yarn.lock
index ca44c7d4ce..977d2169ce 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -11187,10 +11187,10 @@ functions-have-names@^1.2.3:
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
-fuse.js@^6.6.2:
- version "6.6.2"
- resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-6.6.2.tgz#fe463fed4b98c0226ac3da2856a415576dc9a111"
- integrity sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==
+fuse.js@^7.0.0:
+ version "7.0.0"
+ resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-7.0.0.tgz#6573c9fcd4c8268e403b4fc7d7131ffcf99a9eb2"
+ integrity sha512-14F4hBIxqKvD4Zz/XjDc3y94mNZN6pRv3U13Udo0lNLCWRBUsrMv2xwcF/y/Z5sV6+FQW+/ow68cHpm4sunt8Q==
gensync@^1.0.0-beta.2:
version "1.0.0-beta.2"
From bc4516cc0ec7fb27d3e81656e8b5f3f783a1ec48 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 16 Sep 2024 11:36:11 +0200
Subject: [PATCH 73/81] Chore(deps): Bump @safe-global/safe-modules-deployments
(#4172)
Bumps [@safe-global/safe-modules-deployments](https://github.com/safe-global/safe-modules-deployments) from 1.2.0 to 2.2.1.
- [Release notes](https://github.com/safe-global/safe-modules-deployments/releases)
- [Commits](https://github.com/safe-global/safe-modules-deployments/compare/v1.2.0...v2.2.1)
---
updated-dependencies:
- dependency-name: "@safe-global/safe-modules-deployments"
dependency-type: direct:production
update-type: version-update:semver-major
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 5 -----
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/package.json b/package.json
index ba2378b361..4d37d338b9 100644
--- a/package.json
+++ b/package.json
@@ -59,7 +59,7 @@
"@safe-global/safe-apps-sdk": "^9.1.0",
"@safe-global/safe-deployments": "^1.37.3",
"@safe-global/safe-gateway-typescript-sdk": "3.22.3-beta.13",
- "@safe-global/safe-modules-deployments": "^1.2.0",
+ "@safe-global/safe-modules-deployments": "^2.2.1",
"@sentry/react": "^7.91.0",
"@spindl-xyz/attribution-lite": "^1.4.0",
"@walletconnect/utils": "^2.16.1",
diff --git a/yarn.lock b/yarn.lock
index 977d2169ce..145f2571c8 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4193,11 +4193,6 @@
resolved "https://registry.yarnpkg.com/@safe-global/safe-gateway-typescript-sdk/-/safe-gateway-typescript-sdk-3.21.2.tgz#2123a7429c2d9713365f51c359bfc055d4c8e913"
integrity sha512-N9Y2CKPBVbc8FbOKzqepy8TJUY2VILX7bmxV4ruByLJvR9PBnGvGfnOhw975cDn6PmSziXL0RaUWHpSW23rsng==
-"@safe-global/safe-modules-deployments@^1.2.0":
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/@safe-global/safe-modules-deployments/-/safe-modules-deployments-1.2.0.tgz#ca871c3f553cd16cbea1aac8f8be16498329a7d3"
- integrity sha512-/pjHIPaYwGRM5oOB7lc+yf28fWEq7twNP5dJxpLFgG/9UR4E3F+XfFdYkpP22eIvmOkBwCJXJZfPfESh9WSF2w==
-
"@safe-global/safe-modules-deployments@^2.2.1":
version "2.2.1"
resolved "https://registry.yarnpkg.com/@safe-global/safe-modules-deployments/-/safe-modules-deployments-2.2.1.tgz#a8b88f2afc6ec04fed09968fe1e4990ed975c86e"
From 05ceaa26acc53b23921d106841943597d96d1cdd Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 16 Sep 2024 11:36:30 +0200
Subject: [PATCH 74/81] Chore(deps-dev): Bump storybook from 8.0.6 to 8.3.0
(#4171)
Bumps [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) from 8.0.6 to 8.3.0.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v8.3.0/code/lib/cli)
---
updated-dependencies:
- dependency-name: storybook
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
package.json | 2 +-
yarn.lock | 1074 +++++++++++++-------------------------------------
2 files changed, 282 insertions(+), 794 deletions(-)
diff --git a/package.json b/package.json
index 4d37d338b9..154f9e2bec 100644
--- a/package.json
+++ b/package.json
@@ -146,7 +146,7 @@
"jest-environment-jsdom": "^29.6.2",
"mockdate": "^3.0.5",
"prettier": "^2.7.0",
- "storybook": "^8.0.6",
+ "storybook": "^8.3.0",
"ts-prune": "^0.10.3",
"typechain": "^8.3.2",
"typescript": "^5.4.5",
diff --git a/yarn.lock b/yarn.lock
index 145f2571c8..26e15dd047 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -49,13 +49,6 @@
resolved "https://registry.yarnpkg.com/@assemblyscript/loader/-/loader-0.9.4.tgz#a483c54c1253656bb33babd464e3154a173e1577"
integrity sha512-HazVq9zwTVwGmqdwYzu7WyQ6FQVZ7SwET0KKQuKm55jD0IfUpZgN0OPIiZG3zV1iSrVYcN0bdwLRXI/VNCYsUA==
-"@aw-web-design/x-default-browser@1.4.126":
- version "1.4.126"
- resolved "https://registry.yarnpkg.com/@aw-web-design/x-default-browser/-/x-default-browser-1.4.126.tgz#43e4bd8f0314ed907a8718d7e862a203af79bc16"
- integrity sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==
- dependencies:
- default-browser-id "3.0.0"
-
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.7", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2":
version "7.24.2"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae"
@@ -69,7 +62,7 @@
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a"
integrity sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==
-"@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.18.9", "@babel/core@^7.19.6", "@babel/core@^7.23.0", "@babel/core@^7.23.2", "@babel/core@^7.23.9":
+"@babel/core@^7.11.1", "@babel/core@^7.11.6", "@babel/core@^7.12.3", "@babel/core@^7.18.9", "@babel/core@^7.19.6", "@babel/core@^7.23.2":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.4.tgz#1f758428e88e0d8c563874741bc4ffc4f71a4717"
integrity sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==
@@ -383,13 +376,6 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.3"
-"@babel/plugin-syntax-flow@^7.24.1":
- version "7.24.1"
- resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.1.tgz#875c25e3428d7896c87589765fc8b9d32f24bd8d"
- integrity sha512-sxi2kLTI5DeW5vDtMUsk4mTPwvlUDbjOnoWayhynCwrw4QXRld4QEYwqzY8JmQXaJUtgUuCIurtSRH5sn4c7mA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.24.0"
-
"@babel/plugin-syntax-import-assertions@^7.22.5", "@babel/plugin-syntax-import-assertions@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz#db3aad724153a00eaac115a3fb898de544e34971"
@@ -621,14 +607,6 @@
"@babel/helper-plugin-utils" "^7.24.0"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
-"@babel/plugin-transform-flow-strip-types@^7.24.1":
- version "7.24.1"
- resolved "https://registry.yarnpkg.com/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.1.tgz#fa8d0a146506ea195da1671d38eed459242b2dcc"
- integrity sha512-iIYPIWt3dUmUKKE10s3W+jsQ3icFkw0JyRVyY1B7G4yK/nngAOHLVx8xlhA6b/Jzl/Y0nis8gjqhqKtRDQqHWQ==
- dependencies:
- "@babel/helper-plugin-utils" "^7.24.0"
- "@babel/plugin-syntax-flow" "^7.24.1"
-
"@babel/plugin-transform-for-of@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz#67448446b67ab6c091360ce3717e7d3a59e202fd"
@@ -684,7 +662,7 @@
"@babel/helper-module-transforms" "^7.23.3"
"@babel/helper-plugin-utils" "^7.24.0"
-"@babel/plugin-transform-modules-commonjs@^7.23.0", "@babel/plugin-transform-modules-commonjs@^7.24.1":
+"@babel/plugin-transform-modules-commonjs@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9"
integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw==
@@ -726,7 +704,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.24.0"
-"@babel/plugin-transform-nullish-coalescing-operator@^7.22.11", "@babel/plugin-transform-nullish-coalescing-operator@^7.24.1":
+"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz#0cd494bb97cb07d428bd651632cb9d4140513988"
integrity sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw==
@@ -768,7 +746,7 @@
"@babel/helper-plugin-utils" "^7.24.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
-"@babel/plugin-transform-optional-chaining@^7.23.0", "@babel/plugin-transform-optional-chaining@^7.24.1":
+"@babel/plugin-transform-optional-chaining@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz#26e588acbedce1ab3519ac40cc748e380c5291e6"
integrity sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg==
@@ -784,7 +762,7 @@
dependencies:
"@babel/helper-plugin-utils" "^7.24.0"
-"@babel/plugin-transform-private-methods@^7.22.5", "@babel/plugin-transform-private-methods@^7.24.1":
+"@babel/plugin-transform-private-methods@^7.24.1":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz#a0faa1ae87eff077e1e47a5ec81c3aef383dc15a"
integrity sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw==
@@ -1040,15 +1018,6 @@
core-js-compat "^3.31.0"
semver "^6.3.1"
-"@babel/preset-flow@^7.22.15":
- version "7.24.1"
- resolved "https://registry.yarnpkg.com/@babel/preset-flow/-/preset-flow-7.24.1.tgz#da7196c20c2d7dd4e98cfd8b192fe53b5eb6f0bb"
- integrity sha512-sWCV2G9pcqZf+JHyv/RyqEIpFypxdCSxWIxQjpdaQxenNog7cN1pr76hg8u0Fz8Qgg0H4ETkGcJnXL8d4j0PPA==
- dependencies:
- "@babel/helper-plugin-utils" "^7.24.0"
- "@babel/helper-validator-option" "^7.23.5"
- "@babel/plugin-transform-flow-strip-types" "^7.24.1"
-
"@babel/preset-modules@0.1.6-no-external-plugins":
version "0.1.6-no-external-plugins"
resolved "https://registry.yarnpkg.com/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz#ccb88a2c49c817236861fee7826080573b8a923a"
@@ -1070,7 +1039,7 @@
"@babel/plugin-transform-react-jsx-development" "^7.22.5"
"@babel/plugin-transform-react-pure-annotations" "^7.24.1"
-"@babel/preset-typescript@^7.18.6", "@babel/preset-typescript@^7.23.0", "@babel/preset-typescript@^7.23.2":
+"@babel/preset-typescript@^7.18.6", "@babel/preset-typescript@^7.23.2":
version "7.24.1"
resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz#89bdf13a3149a17b3b2a2c9c62547f06db8845ec"
integrity sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ==
@@ -1081,17 +1050,6 @@
"@babel/plugin-transform-modules-commonjs" "^7.24.1"
"@babel/plugin-transform-typescript" "^7.24.1"
-"@babel/register@^7.22.15":
- version "7.23.7"
- resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.23.7.tgz#485a5e7951939d21304cae4af1719fdb887bc038"
- integrity sha512-EjJeB6+kvpk+Y5DAkEAmbOBEFkh9OASx0huoEkqYTFxAZHzOAX2Oh5uwAUuL2rUddqfM0SA+KPXV2TbzoZ2kvQ==
- dependencies:
- clone-deep "^4.0.1"
- find-cache-dir "^2.0.0"
- make-dir "^2.1.0"
- pirates "^4.0.6"
- source-map-support "^0.5.16"
-
"@babel/regjsgen@^0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
@@ -1296,11 +1254,6 @@
dependencies:
"@date-io/core" "^2.17.0"
-"@discoveryjs/json-ext@^0.5.3":
- version "0.5.7"
- resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
- integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
-
"@ducanh2912/next-pwa@^9.7.1":
version "9.7.1"
resolved "https://registry.yarnpkg.com/@ducanh2912/next-pwa/-/next-pwa-9.7.1.tgz#ae88531d7925e03a8a4b14b003cf1b26e767ae65"
@@ -1447,6 +1400,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537"
integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==
+"@esbuild/aix-ppc64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz#51299374de171dbd80bb7d838e1cfce9af36f353"
+ integrity sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==
+
"@esbuild/android-arm64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.4.tgz#74752a09301b8c6b9a415fbda9fb71406a62a7b7"
@@ -1457,6 +1415,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9"
integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==
+"@esbuild/android-arm64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz#58565291a1fe548638adb9c584237449e5e14018"
+ integrity sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==
+
"@esbuild/android-arm@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.4.tgz#c27363e1e280e577d9b5c8fa7c7a3be2a8d79bf5"
@@ -1467,6 +1430,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995"
integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==
+"@esbuild/android-arm@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.1.tgz#5eb8c652d4c82a2421e3395b808e6d9c42c862ee"
+ integrity sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==
+
"@esbuild/android-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.4.tgz#6c9ee03d1488973d928618100048b75b147e0426"
@@ -1477,6 +1445,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98"
integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==
+"@esbuild/android-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.1.tgz#ae19d665d2f06f0f48a6ac9a224b3f672e65d517"
+ integrity sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==
+
"@esbuild/darwin-arm64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.4.tgz#64e2ee945e5932cd49812caa80e8896e937e2f8b"
@@ -1487,6 +1460,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb"
integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==
+"@esbuild/darwin-arm64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz#05b17f91a87e557b468a9c75e9d85ab10c121b16"
+ integrity sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==
+
"@esbuild/darwin-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.4.tgz#d8e26e1b965df284692e4d1263ba69a49b39ac7a"
@@ -1497,6 +1475,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0"
integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==
+"@esbuild/darwin-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz#c58353b982f4e04f0d022284b8ba2733f5ff0931"
+ integrity sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==
+
"@esbuild/freebsd-arm64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.4.tgz#29751a41b242e0a456d89713b228f1da4f45582f"
@@ -1507,6 +1490,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911"
integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==
+"@esbuild/freebsd-arm64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz#f9220dc65f80f03635e1ef96cfad5da1f446f3bc"
+ integrity sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==
+
"@esbuild/freebsd-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.4.tgz#873edc0f73e83a82432460ea59bf568c1e90b268"
@@ -1517,6 +1505,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c"
integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==
+"@esbuild/freebsd-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz#69bd8511fa013b59f0226d1609ac43f7ce489730"
+ integrity sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==
+
"@esbuild/linux-arm64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.4.tgz#659f2fa988d448dbf5010b5cc583be757cc1b914"
@@ -1527,6 +1520,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5"
integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==
+"@esbuild/linux-arm64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz#8050af6d51ddb388c75653ef9871f5ccd8f12383"
+ integrity sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==
+
"@esbuild/linux-arm@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.4.tgz#d5b13a7ec1f1c655ce05c8d319b3950797baee55"
@@ -1537,6 +1535,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c"
integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==
+"@esbuild/linux-arm@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz#ecaabd1c23b701070484990db9a82f382f99e771"
+ integrity sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==
+
"@esbuild/linux-ia32@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.4.tgz#878cd8bf24c9847c77acdb5dd1b2ef6e4fa27a82"
@@ -1547,6 +1550,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa"
integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==
+"@esbuild/linux-ia32@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz#3ed2273214178109741c09bd0687098a0243b333"
+ integrity sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==
+
"@esbuild/linux-loong64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.4.tgz#df890499f6e566b7de3aa2361be6df2b8d5fa015"
@@ -1557,6 +1565,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5"
integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==
+"@esbuild/linux-loong64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz#a0fdf440b5485c81b0fbb316b08933d217f5d3ac"
+ integrity sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==
+
"@esbuild/linux-mips64el@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.4.tgz#76eae4e88d2ce9f4f1b457e93892e802851b6807"
@@ -1567,6 +1580,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa"
integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==
+"@esbuild/linux-mips64el@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz#e11a2806346db8375b18f5e104c5a9d4e81807f6"
+ integrity sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==
+
"@esbuild/linux-ppc64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.4.tgz#c49032f4abbcfa3f747b543a106931fe3dce41ff"
@@ -1577,6 +1595,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20"
integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==
+"@esbuild/linux-ppc64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz#06a2744c5eaf562b1a90937855b4d6cf7c75ec96"
+ integrity sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==
+
"@esbuild/linux-riscv64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.4.tgz#0f815a090772138503ee0465a747e16865bf94b1"
@@ -1587,6 +1610,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300"
integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==
+"@esbuild/linux-riscv64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz#65b46a2892fc0d1af4ba342af3fe0fa4a8fe08e7"
+ integrity sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==
+
"@esbuild/linux-s390x@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.4.tgz#8d2cca20cd4e7c311fde8701d9f1042664f8b92b"
@@ -1597,6 +1625,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685"
integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==
+"@esbuild/linux-s390x@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz#e71ea18c70c3f604e241d16e4e5ab193a9785d6f"
+ integrity sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==
+
"@esbuild/linux-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.4.tgz#f618bec2655de49bff91c588777e37b5e3169d4a"
@@ -1607,6 +1640,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff"
integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==
+"@esbuild/linux-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz#d47f97391e80690d4dfe811a2e7d6927ad9eed24"
+ integrity sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==
+
"@esbuild/netbsd-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.4.tgz#7889744ca4d60f1538d62382b95e90a49687cef2"
@@ -1617,6 +1655,16 @@
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6"
integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==
+"@esbuild/netbsd-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz#44e743c9778d57a8ace4b72f3c6b839a3b74a653"
+ integrity sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==
+
+"@esbuild/openbsd-arm64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz#05c5a1faf67b9881834758c69f3e51b7dee015d7"
+ integrity sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==
+
"@esbuild/openbsd-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.4.tgz#c3e436eb9271a423d2e8436fcb120e3fd90e2b01"
@@ -1627,6 +1675,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf"
integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==
+"@esbuild/openbsd-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz#2e58ae511bacf67d19f9f2dcd9e8c5a93f00c273"
+ integrity sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==
+
"@esbuild/sunos-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.4.tgz#f63f5841ba8c8c1a1c840d073afc99b53e8ce740"
@@ -1637,6 +1690,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f"
integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==
+"@esbuild/sunos-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz#adb022b959d18d3389ac70769cef5a03d3abd403"
+ integrity sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==
+
"@esbuild/win32-arm64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.4.tgz#80be69cec92da4da7781cf7a8351b95cc5a236b0"
@@ -1647,6 +1705,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90"
integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==
+"@esbuild/win32-arm64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz#84906f50c212b72ec360f48461d43202f4c8b9a2"
+ integrity sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==
+
"@esbuild/win32-ia32@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.4.tgz#15dc0ed83d2794872b05d8edc4a358fecf97eb54"
@@ -1657,6 +1720,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23"
integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==
+"@esbuild/win32-ia32@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz#5e3eacc515820ff729e90d0cb463183128e82fac"
+ integrity sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==
+
"@esbuild/win32-x64@0.19.4":
version "0.19.4"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.4.tgz#d46a6e220a717f31f39ae80f49477cc3220be0f0"
@@ -1667,6 +1735,11 @@
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
+"@esbuild/win32-x64@0.23.1":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz#81fd50d11e2c32b2d6241470e3185b70c7b30699"
+ integrity sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==
+
"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0":
version "4.4.0"
resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
@@ -2451,11 +2524,6 @@
resolved "https://registry.yarnpkg.com/@faker-js/faker/-/faker-8.1.0.tgz#e14896f1c57af2495e341dc4c7bf04125c8aeafd"
integrity sha512-38DT60rumHfBYynif3lmtxMqMqmsOQIxQgEuPZxCk2yUYN0eqWpTACgxi0VpidvsJB8CRxCpvP7B3anK85FjtQ==
-"@fal-works/esbuild-plugin-global-externals@^2.1.2":
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/@fal-works/esbuild-plugin-global-externals/-/esbuild-plugin-global-externals-2.1.2.tgz#c05ed35ad82df8e6ac616c68b92c2282bd083ba4"
- integrity sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==
-
"@figspec/components@^1.0.1":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@figspec/components/-/components-1.0.3.tgz#6456970a7298f9969d4d329574435050fcac00d9"
@@ -3717,15 +3785,6 @@
resolved "https://registry.yarnpkg.com/@multiformats/base-x/-/base-x-4.0.1.tgz#95ff0fa58711789d53aefb2590a8b7a4e715d121"
integrity sha512-eMk0b9ReBbV23xXU693TAIrLyeO5iTgBZGSJfpqriG8UkYvr/hC9u9pyMlAakDNHWmbhMZCDs6KQO0jzKD8OTw==
-"@ndelangen/get-tarball@^3.0.7":
- version "3.0.9"
- resolved "https://registry.yarnpkg.com/@ndelangen/get-tarball/-/get-tarball-3.0.9.tgz#727ff4454e65f34707e742a59e5e6b1f525d8964"
- integrity sha512-9JKTEik4vq+yGosHYhZ1tiH/3WpUS0Nh0kej4Agndhox8pAdWhEx5knFVRcb/ya9knCRCs1rPxNrSXTDdfVqpA==
- dependencies:
- gunzip-maybe "^1.4.2"
- pump "^3.0.0"
- tar-fs "^2.1.1"
-
"@next/bundle-analyzer@^13.5.6":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-13.5.6.tgz#3c73f2e15ff5507317b37b87ce984bac5a5d7ad0"
@@ -4679,26 +4738,6 @@
ts-dedent "^2.0.0"
util-deprecate "^1.0.2"
-"@storybook/builder-manager@8.0.6":
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/@storybook/builder-manager/-/builder-manager-8.0.6.tgz#ec2fffddbcaa3680380f1ff529b585452289bd0d"
- integrity sha512-N61Gh9FKsSYvsbdBy5qFvq1anTIuUAjh2Z+ezDMlxnfMGG77nZP9heuy1NnCaYCTFzl+lq4BsmRfXXDcKtSPRA==
- dependencies:
- "@fal-works/esbuild-plugin-global-externals" "^2.1.2"
- "@storybook/core-common" "8.0.6"
- "@storybook/manager" "8.0.6"
- "@storybook/node-logger" "8.0.6"
- "@types/ejs" "^3.1.1"
- "@yarnpkg/esbuild-plugin-pnp" "^3.0.0-rc.10"
- browser-assert "^1.2.1"
- ejs "^3.1.8"
- esbuild "^0.18.0 || ^0.19.0 || ^0.20.0"
- esbuild-plugin-alias "^0.2.1"
- express "^4.17.3"
- fs-extra "^11.1.0"
- process "^0.11.10"
- util "^0.12.4"
-
"@storybook/builder-webpack5@8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/builder-webpack5/-/builder-webpack5-8.0.6.tgz#53ee640ef9050149ac1303c4ec6fe6cb8ffba341"
@@ -4750,48 +4789,6 @@
telejson "^7.2.0"
tiny-invariant "^1.3.1"
-"@storybook/cli@8.0.6":
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/@storybook/cli/-/cli-8.0.6.tgz#c9b789474be5b51182dc78e30ca06f7b7961b49d"
- integrity sha512-gAnl9soQUu1BtB4sANaqaaeTZAt/ThBSwCdzSLut5p21fP4ovi3FeP7hcDCJbyJZ/AvnD4k6leDrqRQxMVPr0A==
- dependencies:
- "@babel/core" "^7.23.0"
- "@babel/types" "^7.23.0"
- "@ndelangen/get-tarball" "^3.0.7"
- "@storybook/codemod" "8.0.6"
- "@storybook/core-common" "8.0.6"
- "@storybook/core-events" "8.0.6"
- "@storybook/core-server" "8.0.6"
- "@storybook/csf-tools" "8.0.6"
- "@storybook/node-logger" "8.0.6"
- "@storybook/telemetry" "8.0.6"
- "@storybook/types" "8.0.6"
- "@types/semver" "^7.3.4"
- "@yarnpkg/fslib" "2.10.3"
- "@yarnpkg/libzip" "2.3.0"
- chalk "^4.1.0"
- commander "^6.2.1"
- cross-spawn "^7.0.3"
- detect-indent "^6.1.0"
- envinfo "^7.7.3"
- execa "^5.0.0"
- find-up "^5.0.0"
- fs-extra "^11.1.0"
- get-npm-tarball-url "^2.0.3"
- giget "^1.0.0"
- globby "^11.0.2"
- jscodeshift "^0.15.1"
- leven "^3.1.0"
- ora "^5.4.1"
- prettier "^3.1.1"
- prompts "^2.4.0"
- read-pkg-up "^7.0.1"
- semver "^7.3.7"
- strip-json-comments "^3.0.1"
- tempy "^1.0.1"
- tiny-invariant "^1.3.1"
- ts-dedent "^2.0.0"
-
"@storybook/client-logger@8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-8.0.6.tgz#70a96ad63318dcf856edeca366a8d21576f8cc09"
@@ -4799,27 +4796,6 @@
dependencies:
"@storybook/global" "^5.0.0"
-"@storybook/codemod@8.0.6":
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/@storybook/codemod/-/codemod-8.0.6.tgz#c6a1f40697a8409b01481042d41b8709f74aa85c"
- integrity sha512-IMaTVI+EvmFxkz4leKWKForPC3LFxzfeTmd/QnTNF3nCeyvmIXvP01pQXRjro0+XcGDncEStuxa1d9ClMlac9Q==
- dependencies:
- "@babel/core" "^7.23.2"
- "@babel/preset-env" "^7.23.2"
- "@babel/types" "^7.23.0"
- "@storybook/csf" "^0.1.2"
- "@storybook/csf-tools" "8.0.6"
- "@storybook/node-logger" "8.0.6"
- "@storybook/types" "8.0.6"
- "@types/cross-spawn" "^6.0.2"
- cross-spawn "^7.0.3"
- globby "^11.0.2"
- jscodeshift "^0.15.1"
- lodash "^4.17.21"
- prettier "^3.1.1"
- recast "^0.23.5"
- tiny-invariant "^1.3.1"
-
"@storybook/components@8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/components/-/components-8.0.6.tgz#62df4e257d5d456df4ce373e89fc3eda2c5ceb57"
@@ -4876,55 +4852,6 @@
dependencies:
ts-dedent "^2.0.0"
-"@storybook/core-server@8.0.6":
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/@storybook/core-server/-/core-server-8.0.6.tgz#e51fb7103448e18349e10289f7eb46ae4dfd60dd"
- integrity sha512-COmcjrry8vZXDh08ZGbfDz2bFB4of5wnwOwYf8uwlVND6HnhQzV22On1s3/p8qw+dKOpjpwDdHWtMnndnPNuqQ==
- dependencies:
- "@aw-web-design/x-default-browser" "1.4.126"
- "@babel/core" "^7.23.9"
- "@discoveryjs/json-ext" "^0.5.3"
- "@storybook/builder-manager" "8.0.6"
- "@storybook/channels" "8.0.6"
- "@storybook/core-common" "8.0.6"
- "@storybook/core-events" "8.0.6"
- "@storybook/csf" "^0.1.2"
- "@storybook/csf-tools" "8.0.6"
- "@storybook/docs-mdx" "3.0.0"
- "@storybook/global" "^5.0.0"
- "@storybook/manager" "8.0.6"
- "@storybook/manager-api" "8.0.6"
- "@storybook/node-logger" "8.0.6"
- "@storybook/preview-api" "8.0.6"
- "@storybook/telemetry" "8.0.6"
- "@storybook/types" "8.0.6"
- "@types/detect-port" "^1.3.0"
- "@types/node" "^18.0.0"
- "@types/pretty-hrtime" "^1.0.0"
- "@types/semver" "^7.3.4"
- better-opn "^3.0.2"
- chalk "^4.1.0"
- cli-table3 "^0.6.1"
- compression "^1.7.4"
- detect-port "^1.3.0"
- express "^4.17.3"
- fs-extra "^11.1.0"
- globby "^11.0.2"
- ip "^2.0.1"
- lodash "^4.17.21"
- open "^8.4.0"
- pretty-hrtime "^1.0.3"
- prompts "^2.4.0"
- read-pkg-up "^7.0.1"
- semver "^7.3.7"
- telejson "^7.2.0"
- tiny-invariant "^1.3.1"
- ts-dedent "^2.0.0"
- util "^0.12.4"
- util-deprecate "^1.0.2"
- watchpack "^2.2.0"
- ws "^8.2.3"
-
"@storybook/core-webpack@8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/core-webpack/-/core-webpack-8.0.6.tgz#fe18de9e728437d1f7e48192dbfd559bb9a4b33f"
@@ -4936,6 +4863,23 @@
"@types/node" "^18.0.0"
ts-dedent "^2.0.0"
+"@storybook/core@8.3.0":
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/@storybook/core/-/core-8.3.0.tgz#c08ff10405fa935044678c8ae92c7be14dd01bdb"
+ integrity sha512-UeErpD0xRIP2nFA2TjPYxtEyv24O6VRfq2XXU5ki2QPYnxOxAPBbrMHCADjgBwNS4S2NUWTaVBYxybISVbrj+w==
+ dependencies:
+ "@storybook/csf" "^0.1.11"
+ "@types/express" "^4.17.21"
+ browser-assert "^1.2.1"
+ esbuild "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0"
+ esbuild-register "^3.5.0"
+ express "^4.19.2"
+ process "^0.11.10"
+ recast "^0.23.5"
+ semver "^7.6.2"
+ util "^0.12.5"
+ ws "^8.2.3"
+
"@storybook/csf-plugin@8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/csf-plugin/-/csf-plugin-8.0.6.tgz#1e907002b24840e935c1b747b535f20d369ade3d"
@@ -4966,6 +4910,13 @@
dependencies:
lodash "^4.17.15"
+"@storybook/csf@^0.1.11":
+ version "0.1.11"
+ resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.11.tgz#ad685a4fe564a47a6b73571c2e7c07b526f4f71b"
+ integrity sha512-dHYFQH3mA+EtnCkHXzicbLgsvzYjcDJ1JWsogbItZogkPHgSJM/Wr71uMkcvw8v9mmCyP4NpXJuu6bPoVsOnzg==
+ dependencies:
+ type-fest "^2.19.0"
+
"@storybook/csf@^0.1.2":
version "0.1.3"
resolved "https://registry.yarnpkg.com/@storybook/csf/-/csf-0.1.3.tgz#79047a4dece94ba7c8e78003723e9bd9e071379a"
@@ -4973,11 +4924,6 @@
dependencies:
type-fest "^2.19.0"
-"@storybook/docs-mdx@3.0.0":
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/@storybook/docs-mdx/-/docs-mdx-3.0.0.tgz#5c9b5ce35dcb00ad8aa5dddbabf52ad09fab3974"
- integrity sha512-NmiGXl2HU33zpwTv1XORe9XG9H+dRUC1Jl11u92L4xr062pZtrShLmD4VKIsOQujxhhOrbxpwhNOt+6TdhyIdQ==
-
"@storybook/docs-tools@8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/docs-tools/-/docs-tools-8.0.6.tgz#691150506d32d389e15ea0cbb5132a6f4a9c8d85"
@@ -5035,11 +4981,6 @@
telejson "^7.2.0"
ts-dedent "^2.0.0"
-"@storybook/manager@8.0.6":
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/@storybook/manager/-/manager-8.0.6.tgz#c2ab7077c6f77eaf7928b7dcd3335127eacd2997"
- integrity sha512-wdL3lG72qrCOLkxEUW49+hmwA4fIFXFvAEU7wVgEt4KyRRGWhHa8Dr/5Tnq54CWJrA+BTrTPHaoo/Vu4BAjgow==
-
"@storybook/nextjs@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/nextjs/-/nextjs-8.0.6.tgz#9fa2589d92c8b5c80cde7491998161e5d91af17b"
@@ -5196,20 +5137,6 @@
memoizerific "^1.11.3"
qs "^6.10.0"
-"@storybook/telemetry@8.0.6":
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/@storybook/telemetry/-/telemetry-8.0.6.tgz#5a7cf64fb7fb6f3fc3ca2e9a871e383782415095"
- integrity sha512-kzxhhzGRSBYR4oe/Vlp/adKVxD8KWbIDMCgLWaINe14ILfEmpyrC00MXRSjS1tMF1qfrtn600Oe/xkHFQUpivQ==
- dependencies:
- "@storybook/client-logger" "8.0.6"
- "@storybook/core-common" "8.0.6"
- "@storybook/csf-tools" "8.0.6"
- chalk "^4.1.0"
- detect-package-manager "^2.0.1"
- fetch-retry "^5.0.2"
- fs-extra "^11.1.0"
- read-pkg-up "^7.0.1"
-
"@storybook/test@8.0.6", "@storybook/test@^8.0.6":
version "8.0.6"
resolved "https://registry.yarnpkg.com/@storybook/test/-/test-8.0.6.tgz#6c2d38d9189ec6a0640c3267ad68fc64564ef52d"
@@ -5705,13 +5632,6 @@
dependencies:
"@types/node" "*"
-"@types/cross-spawn@^6.0.2":
- version "6.0.6"
- resolved "https://registry.yarnpkg.com/@types/cross-spawn/-/cross-spawn-6.0.6.tgz#0163d0b79a6f85409e0decb8dcca17147f81fd22"
- integrity sha512-fXRhhUkG4H3TQk5dBhQ7m/JDdSNHKwR2BBia62lhwEIq9xGiQKLxd6LymNhn47SjXhsUEPmxi+PKw2OkW4LLjA==
- dependencies:
- "@types/node" "*"
-
"@types/debug@^4.1.7":
version "4.1.9"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.9.tgz#906996938bc672aaf2fb8c0d3733ae1dda05b005"
@@ -5719,11 +5639,6 @@
dependencies:
"@types/ms" "*"
-"@types/detect-port@^1.3.0":
- version "1.3.5"
- resolved "https://registry.yarnpkg.com/@types/detect-port/-/detect-port-1.3.5.tgz#deecde143245989dee0e82115f3caba5ee0ea747"
- integrity sha512-Rf3/lB9WkDfIL9eEKaSYKc+1L/rNVYBjThk22JTqQw0YozXarX8YljFAz+HCoC6h4B4KwCMsBPZHaFezwT4BNA==
-
"@types/doctrine@^0.0.3":
version "0.0.3"
resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.3.tgz#e892d293c92c9c1d3f9af72c15a554fbc7e0895a"
@@ -5734,11 +5649,6 @@
resolved "https://registry.yarnpkg.com/@types/doctrine/-/doctrine-0.0.9.tgz#d86a5f452a15e3e3113b99e39616a9baa0f9863f"
integrity sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==
-"@types/ejs@^3.1.1":
- version "3.1.5"
- resolved "https://registry.yarnpkg.com/@types/ejs/-/ejs-3.1.5.tgz#49d738257cc73bafe45c13cb8ff240683b4d5117"
- integrity sha512-nv+GSx77ZtXiJzwKdsASqi+YQ5Z7vwHsTP0JY2SiQgjGckkBRKZnk8nIM+7oUZ1VCtuTz0+By4qVR7fqzp/Dfg==
-
"@types/emscripten@^1.39.6":
version "1.39.10"
resolved "https://registry.yarnpkg.com/@types/emscripten/-/emscripten-1.39.10.tgz#da6e58a6171b46a41d3694f812d845d515c77e18"
@@ -5774,7 +5684,7 @@
"@types/range-parser" "*"
"@types/send" "*"
-"@types/express@^4.7.0":
+"@types/express@^4.17.21", "@types/express@^4.7.0":
version "4.17.21"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d"
integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==
@@ -5979,11 +5889,6 @@
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f"
integrity sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==
-"@types/pretty-hrtime@^1.0.0":
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/@types/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#ee1bd8c9f7a01b3445786aad0ef23aba5f511a44"
- integrity sha512-nj39q0wAIdhwn7DGUyT9irmsKK1tV0bd5WFEhgpqNTMFZ8cE+jieuTphCW0tfdm47S2zVT5mr09B28b1chmQMA==
-
"@types/prop-types@*", "@types/prop-types@^15.7.11":
version "15.7.11"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.11.tgz#2596fb352ee96a1379c657734d4b913a613ad563"
@@ -7079,13 +6984,6 @@
resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d"
integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==
-"@yarnpkg/esbuild-plugin-pnp@^3.0.0-rc.10":
- version "3.0.0-rc.15"
- resolved "https://registry.yarnpkg.com/@yarnpkg/esbuild-plugin-pnp/-/esbuild-plugin-pnp-3.0.0-rc.15.tgz#4e40e7d2eb28825c9a35ab9d04c363931d7c0e67"
- integrity sha512-kYzDJO5CA9sy+on/s2aIW0411AklfCi8Ck/4QDivOqsMKpStZA2SsR+X27VTggGwpStWaLrjJcDcdDMowtG8MA==
- dependencies:
- tslib "^2.4.0"
-
"@yarnpkg/fslib@2.10.3":
version "2.10.3"
resolved "https://registry.yarnpkg.com/@yarnpkg/fslib/-/fslib-2.10.3.tgz#a8c9893df5d183cf6362680b9f1c6d7504dd5717"
@@ -7132,7 +7030,7 @@ abort-controller@^3.0.0:
dependencies:
event-target-shim "^5.0.0"
-accepts@~1.3.5, accepts@~1.3.8:
+accepts@~1.3.8:
version "1.3.8"
resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
integrity sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==
@@ -7183,11 +7081,6 @@ acorn@^8.0.4, acorn@^8.1.0, acorn@^8.10.0, acorn@^8.11.3, acorn@^8.7.1, acorn@^8
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
-address@^1.0.1:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/address/-/address-1.2.2.tgz#2b5248dac5485a6390532c6a517fda2e3faac89e"
- integrity sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==
-
adjust-sourcemap-loader@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz#fc4a0fd080f7d10471f30a7320f25560ade28c99"
@@ -7628,11 +7521,6 @@ b4a@^1.6.4:
resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.6.tgz#a4cc349a3851987c3c4ac2d7785c18744f6da9ba"
integrity sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==
-babel-core@^7.0.0-bridge.0:
- version "7.0.0-bridge.0"
- resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece"
- integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==
-
babel-jest@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/babel-jest/-/babel-jest-29.7.0.tgz#f4369919225b684c56085998ac63dbd05be020d5"
@@ -7814,19 +7702,12 @@ bech32@^2.0.0:
resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355"
integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==
-better-opn@^3.0.2:
- version "3.0.2"
- resolved "https://registry.yarnpkg.com/better-opn/-/better-opn-3.0.2.tgz#f96f35deaaf8f34144a4102651babcf00d1d8817"
- integrity sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==
- dependencies:
- open "^8.0.4"
-
big-integer@1.6.36:
version "1.6.36"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36"
integrity sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==
-big-integer@^1.6.44, big-integer@^1.6.48:
+big-integer@^1.6.48:
version "1.6.52"
resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85"
integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==
@@ -7877,7 +7758,7 @@ bitcoin-ops@^1.3.0, bitcoin-ops@^1.4.1:
resolved "https://registry.yarnpkg.com/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz#e45de620398e22fd4ca6023de43974ff42240278"
integrity sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==
-bl@^4.0.3, bl@^4.1.0:
+bl@^4.0.3:
version "4.1.0"
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
@@ -7981,13 +7862,6 @@ bowser@^2.11.0:
resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f"
integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==
-bplist-parser@^0.2.0:
- version "0.2.0"
- resolved "https://registry.yarnpkg.com/bplist-parser/-/bplist-parser-0.2.0.tgz#43a9d183e5bf9d545200ceac3e712f79ebbe8d0e"
- integrity sha512-z0M+byMThzQmD9NILRniCUXYsYpjwnlO8N5uCFaCqIOpqRsJCrQL9NK3JsD67CN5a08nF5oIL2bD6loTdHOuKw==
- dependencies:
- big-integer "^1.6.44"
-
brace-expansion@^1.1.7:
version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
@@ -8075,13 +7949,6 @@ browserify-sign@^4.0.0:
readable-stream "^2.3.8"
safe-buffer "^5.2.1"
-browserify-zlib@^0.1.4:
- version "0.1.4"
- resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.1.4.tgz#bb35f8a519f600e0fa6b8485241c979d0141fb2d"
- integrity sha512-19OEpq7vWgsH6WkvkBJQDFvJS1uPcbFOQ4v9CU839dO+ZZXUZO6XpE6hNCqvlIIj+4fZvRiJ6DsAQ382GwiyTQ==
- dependencies:
- pako "~0.2.0"
-
browserify-zlib@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f"
@@ -8204,11 +8071,6 @@ bytebuffer@^5.0.1:
dependencies:
long "~3"
-bytes@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048"
- integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==
-
bytes@3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5"
@@ -8364,11 +8226,6 @@ chownr@^1.1.1:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
-chownr@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
- integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
-
chromatic@^11.3.0:
version "11.3.0"
resolved "https://registry.yarnpkg.com/chromatic/-/chromatic-11.3.0.tgz#d46b7aac1a0eaed29a765645eaf93c484220174c"
@@ -8402,7 +8259,7 @@ 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, citty@^0.1.6:
+citty@^0.1.3, citty@^0.1.4:
version "0.1.6"
resolved "https://registry.yarnpkg.com/citty/-/citty-0.1.6.tgz#0f7904da1ed4625e1a9ea7e0fa780981aab7c5e4"
integrity sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==
@@ -8456,12 +8313,7 @@ cli-cursor@^3.1.0:
dependencies:
restore-cursor "^3.1.0"
-cli-spinners@^2.5.0:
- version "2.9.2"
- resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.9.2.tgz#1773a8f4b9c4d6ac31563df53b3fc1d79462fe41"
- integrity sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==
-
-cli-table3@^0.6.1, cli-table3@~0.6.1:
+cli-table3@~0.6.1:
version "0.6.4"
resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.4.tgz#d1c536b8a3f2e7bec58f67ac9e5769b1b30088b0"
integrity sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==
@@ -8510,20 +8362,6 @@ cliui@^8.0.1:
strip-ansi "^6.0.1"
wrap-ansi "^7.0.0"
-clone-deep@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387"
- integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==
- dependencies:
- is-plain-object "^2.0.4"
- kind-of "^6.0.2"
- shallow-clone "^3.0.0"
-
-clone@^1.0.2:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
- integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
-
clsx@^1.1.0, clsx@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.2.1.tgz#0ddc4a20a549b59c93a4116bb26f5294ca17dc12"
@@ -8661,26 +8499,6 @@ commondir@^1.0.1:
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==
-compressible@~2.0.16:
- version "2.0.18"
- resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba"
- integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==
- dependencies:
- mime-db ">= 1.43.0 < 2"
-
-compression@^1.7.4:
- version "1.7.4"
- resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f"
- integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==
- dependencies:
- accepts "~1.3.5"
- bytes "3.0.0"
- compressible "~2.0.16"
- debug "2.6.9"
- on-headers "~1.0.2"
- safe-buffer "5.1.2"
- vary "~1.1.2"
-
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -9188,21 +9006,6 @@ deepmerge@^4.2.2:
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
-default-browser-id@3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/default-browser-id/-/default-browser-id-3.0.0.tgz#bee7bbbef1f4e75d31f98f4d3f1556a14cea790c"
- integrity sha512-OZ1y3y0SqSICtE8DE4S8YOE9UZOJ8wO16fKWVP5J1Qz42kV9jcnMVFrEE/noXb/ss3Q4pZIH79kxofzyNNtUNA==
- dependencies:
- bplist-parser "^0.2.0"
- untildify "^4.0.0"
-
-defaults@^1.0.3:
- version "1.0.4"
- resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.4.tgz#b0b02062c1e2aa62ff5d9528f0f98baa90978d7a"
- integrity sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==
- dependencies:
- clone "^1.0.2"
-
define-data-property@^1.0.1, define-data-property@^1.1.2:
version "1.1.4"
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
@@ -9212,11 +9015,6 @@ define-data-property@^1.0.1, define-data-property@^1.1.2:
es-errors "^1.3.0"
gopd "^1.0.1"
-define-lazy-prop@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
- integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
-
define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
@@ -9226,7 +9024,7 @@ define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
-defu@^6.1.2, defu@^6.1.3, defu@^6.1.4:
+defu@^6.1.2, defu@^6.1.3:
version "6.1.4"
resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479"
integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==
@@ -9306,11 +9104,6 @@ detect-browser@5.3.0:
resolved "https://registry.yarnpkg.com/detect-browser/-/detect-browser-5.3.0.tgz#9705ef2bddf46072d0f7265a1fe300e36fe7ceca"
integrity sha512-53rsFbGdwMwlF7qvCt0ypLM5V5/Mbl0szB7GPN8y9NCcbknYOeVVXdrXEq+90IwAfrrzt6Hd+u2E2ntakICU8w==
-detect-indent@^6.1.0:
- version "6.1.0"
- resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6"
- integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==
-
detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
@@ -9326,21 +9119,6 @@ detect-newline@^3.0.0:
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
integrity sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==
-detect-package-manager@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/detect-package-manager/-/detect-package-manager-2.0.1.tgz#6b182e3ae5e1826752bfef1de9a7b828cffa50d8"
- integrity sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==
- dependencies:
- execa "^5.1.1"
-
-detect-port@^1.3.0:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/detect-port/-/detect-port-1.5.1.tgz#451ca9b6eaf20451acb0799b8ab40dff7718727b"
- integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==
- dependencies:
- address "^1.0.1"
- debug "4"
-
diff-sequences@^29.6.3:
version "29.6.3"
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
@@ -9494,16 +9272,6 @@ duplexer@^0.1.2:
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==
-duplexify@^3.5.0, duplexify@^3.6.0:
- version "3.7.1"
- resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309"
- integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==
- dependencies:
- end-of-stream "^1.0.0"
- inherits "^2.0.1"
- readable-stream "^2.0.0"
- stream-shift "^1.0.0"
-
duplexify@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.2.tgz#18b4f8d28289132fa0b9573c898d9f903f81c7b0"
@@ -9551,7 +9319,7 @@ eip55@^2.1.1:
dependencies:
keccak "^3.0.3"
-ejs@^3.1.6, ejs@^3.1.8:
+ejs@^3.1.6:
version "3.1.10"
resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.10.tgz#69ab8358b14e896f80cc39e62087b88500c3ac3b"
integrity sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==
@@ -9637,7 +9405,7 @@ encodeurl@~2.0.0:
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
-end-of-stream@^1.0.0, end-of-stream@^1.1.0, end-of-stream@^1.4.1:
+end-of-stream@^1.1.0, end-of-stream@^1.4.1:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
@@ -9679,11 +9447,6 @@ entities@^4.4.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
-envinfo@^7.7.3:
- version "7.12.0"
- resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.12.0.tgz#b56723b39c2053d67ea5714f026d05d4f5cc7acd"
- integrity sha512-Iw9rQJBGpJRd3rwXm9ft/JiGoAZmLxxJZELYDQoPRZ4USVhkKtIcNBPw6U+/K2mBpaqM25JSV6Yl4Az9vO2wJg==
-
err-code@^3.0.0, err-code@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920"
@@ -9889,11 +9652,6 @@ es6-weak-map@^2.0.3:
es6-iterator "^2.0.3"
es6-symbol "^3.1.1"
-esbuild-plugin-alias@^0.2.1:
- version "0.2.1"
- resolved "https://registry.yarnpkg.com/esbuild-plugin-alias/-/esbuild-plugin-alias-0.2.1.tgz#45a86cb941e20e7c2bc68a2bea53562172494fcb"
- integrity sha512-jyfL/pwPqaFXyKnj8lP8iLk6Z0m099uXR45aSN8Av1XD4vhvQutxxPzgA2bTcAwQpa1zCXDcWOlhFgyP3GKqhQ==
-
esbuild-register@^3.5.0:
version "3.5.0"
resolved "https://registry.yarnpkg.com/esbuild-register/-/esbuild-register-3.5.0.tgz#449613fb29ab94325c722f560f800dd946dc8ea8"
@@ -9930,6 +9688,36 @@ esbuild-register@^3.5.0:
"@esbuild/win32-ia32" "0.20.2"
"@esbuild/win32-x64" "0.20.2"
+"esbuild@^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0":
+ version "0.23.1"
+ resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.23.1.tgz#40fdc3f9265ec0beae6f59824ade1bd3d3d2dab8"
+ integrity sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==
+ optionalDependencies:
+ "@esbuild/aix-ppc64" "0.23.1"
+ "@esbuild/android-arm" "0.23.1"
+ "@esbuild/android-arm64" "0.23.1"
+ "@esbuild/android-x64" "0.23.1"
+ "@esbuild/darwin-arm64" "0.23.1"
+ "@esbuild/darwin-x64" "0.23.1"
+ "@esbuild/freebsd-arm64" "0.23.1"
+ "@esbuild/freebsd-x64" "0.23.1"
+ "@esbuild/linux-arm" "0.23.1"
+ "@esbuild/linux-arm64" "0.23.1"
+ "@esbuild/linux-ia32" "0.23.1"
+ "@esbuild/linux-loong64" "0.23.1"
+ "@esbuild/linux-mips64el" "0.23.1"
+ "@esbuild/linux-ppc64" "0.23.1"
+ "@esbuild/linux-riscv64" "0.23.1"
+ "@esbuild/linux-s390x" "0.23.1"
+ "@esbuild/linux-x64" "0.23.1"
+ "@esbuild/netbsd-x64" "0.23.1"
+ "@esbuild/openbsd-arm64" "0.23.1"
+ "@esbuild/openbsd-x64" "0.23.1"
+ "@esbuild/sunos-x64" "0.23.1"
+ "@esbuild/win32-arm64" "0.23.1"
+ "@esbuild/win32-ia32" "0.23.1"
+ "@esbuild/win32-x64" "0.23.1"
+
esbuild@^0.19.2:
version "0.19.4"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.4.tgz#cdf5c4c684956d550bc3c6d0c01dac7fef6c75b1"
@@ -10598,21 +10386,6 @@ execa@^5.0.0, execa@^5.1.1:
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
-execa@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c"
- integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==
- dependencies:
- cross-spawn "^7.0.3"
- get-stream "^8.0.1"
- human-signals "^5.0.0"
- is-stream "^3.0.0"
- merge-stream "^2.0.0"
- npm-run-path "^5.1.0"
- onetime "^6.0.0"
- signal-exit "^4.1.0"
- strip-final-newline "^3.0.0"
-
executable@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/executable/-/executable-4.1.1.tgz#41532bff361d3e57af4d763b70582db18f5d133c"
@@ -10688,6 +10461,43 @@ express@^4.17.3:
utils-merge "1.0.1"
vary "~1.1.2"
+express@^4.19.2:
+ version "4.21.0"
+ resolved "https://registry.yarnpkg.com/express/-/express-4.21.0.tgz#d57cb706d49623d4ac27833f1cbc466b668eb915"
+ integrity sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng==
+ dependencies:
+ accepts "~1.3.8"
+ array-flatten "1.1.1"
+ body-parser "1.20.3"
+ content-disposition "0.5.4"
+ content-type "~1.0.4"
+ cookie "0.6.0"
+ cookie-signature "1.0.6"
+ debug "2.6.9"
+ depd "2.0.0"
+ encodeurl "~2.0.0"
+ escape-html "~1.0.3"
+ etag "~1.8.1"
+ finalhandler "1.3.1"
+ fresh "0.5.2"
+ http-errors "2.0.0"
+ merge-descriptors "1.0.3"
+ methods "~1.1.2"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ path-to-regexp "0.1.10"
+ proxy-addr "~2.0.7"
+ qs "6.13.0"
+ range-parser "~1.2.1"
+ safe-buffer "5.2.1"
+ send "0.19.0"
+ serve-static "1.16.2"
+ setprototypeof "1.2.0"
+ statuses "2.0.1"
+ type-is "~1.6.18"
+ utils-merge "1.0.1"
+ vary "~1.1.2"
+
ext@^1.1.2:
version "1.7.0"
resolved "https://registry.yarnpkg.com/ext/-/ext-1.7.0.tgz#0ea4383c0103d60e70be99e9a7f11027a33c4f5f"
@@ -10817,11 +10627,6 @@ fd-slicer@~1.1.0:
dependencies:
pend "~1.2.0"
-fetch-retry@^5.0.2:
- version "5.0.6"
- resolved "https://registry.yarnpkg.com/fetch-retry/-/fetch-retry-5.0.6.tgz#17d0bc90423405b7a88b74355bf364acd2a7fa56"
- integrity sha512-3yurQZ2hD9VISAhJJP9bpYFNQrHHBXE2JxxjY5aLEcDi46RmAzJE2OC9FAde0yis5ElW0jTTzs0zfg/Cca4XqQ==
-
figures@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af"
@@ -10898,14 +10703,18 @@ finalhandler@1.2.0:
statuses "2.0.1"
unpipe "~1.0.0"
-find-cache-dir@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7"
- integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==
+finalhandler@1.3.1:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019"
+ integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==
dependencies:
- commondir "^1.0.1"
- make-dir "^2.0.0"
- pkg-dir "^3.0.0"
+ debug "2.6.9"
+ encodeurl "~2.0.0"
+ escape-html "~1.0.3"
+ on-finished "2.4.1"
+ parseurl "~1.3.3"
+ statuses "2.0.1"
+ unpipe "~1.0.0"
find-cache-dir@^3.0.0, find-cache-dir@^3.3.1:
version "3.3.2"
@@ -10936,13 +10745,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"
@@ -11013,11 +10815,6 @@ flatted@^3.2.9:
resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
-flow-parser@0.*:
- version "0.233.0"
- resolved "https://registry.yarnpkg.com/flow-parser/-/flow-parser-0.233.0.tgz#b983e65812d5ecae79f08ae3ed8ad2e131a9b966"
- integrity sha512-E/mv51GYJfLuRX6fZnw4M52gBxYa8pkHUOgNEZOcQK2RTXS8YXeU5rlalkTcY99UpwbeNVCSUFKaavpOksi/pQ==
-
follow-redirects@^1.14.8, follow-redirects@^1.15.0:
version "1.15.6"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
@@ -11140,13 +10937,6 @@ fs-extra@^9.0.1, fs-extra@^9.1.0:
jsonfile "^6.0.1"
universalify "^2.0.0"
-fs-minipass@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb"
- integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==
- dependencies:
- minipass "^3.0.0"
-
fs-monkey@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/fs-monkey/-/fs-monkey-1.0.5.tgz#fe450175f0db0d7ea758102e1d84096acb925788"
@@ -11213,11 +11003,6 @@ get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@
has-symbols "^1.0.3"
hasown "^2.0.0"
-get-npm-tarball-url@^2.0.3:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/get-npm-tarball-url/-/get-npm-tarball-url-2.1.0.tgz#cbd6bb25884622bc3191c761466c93ac83343213"
- integrity sha512-ro+DiMu5DXgRBabqXupW38h7WPZ9+Ad8UjwhvsmmN8w1sU7ab0nzAXvVZ4kqYg57OrqomRtJvepX5/xvFKNtjA==
-
get-own-enumerable-property-symbols@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664"
@@ -11245,11 +11030,6 @@ get-stream@^6.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
-get-stream@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2"
- integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==
-
get-symbol-description@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5"
@@ -11280,20 +11060,6 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
-giget@^1.0.0:
- version "1.2.3"
- resolved "https://registry.yarnpkg.com/giget/-/giget-1.2.3.tgz#ef6845d1140e89adad595f7f3bb60aa31c672cb6"
- integrity sha512-8EHPljDvs7qKykr6uw8b+lqLiUc/vUg+KVTI0uND4s63TdsZM2Xus3mflvF0DDG9SiM4RlCkFGL+7aAjRmV7KA==
- dependencies:
- citty "^0.1.6"
- consola "^3.2.3"
- defu "^6.1.4"
- node-fetch-native "^1.6.3"
- nypm "^0.3.8"
- ohash "^1.1.3"
- pathe "^1.1.2"
- tar "^6.2.0"
-
github-from-package@0.0.0:
version "0.0.0"
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
@@ -11400,7 +11166,7 @@ globalyzer@0.1.0:
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
-globby@^11.0.1, globby@^11.0.2, globby@^11.1.0:
+globby@^11.0.1, globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
@@ -11435,7 +11201,7 @@ gopd@^1.0.1:
dependencies:
get-intrinsic "^1.1.3"
-graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
+graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.9:
version "4.2.11"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
@@ -11445,18 +11211,6 @@ graphemer@^1.4.0:
resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6"
integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==
-gunzip-maybe@^1.4.2:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/gunzip-maybe/-/gunzip-maybe-1.4.2.tgz#b913564ae3be0eda6f3de36464837a9cd94b98ac"
- integrity sha512-4haO1M4mLO91PW57BMsDFf75UmwoRX0GkdD+Faw+Lr+r/OZrOCS0pIBwOL1xCKQqnQzbNFGgK2V2CpBUPeFNTw==
- dependencies:
- browserify-zlib "^0.1.4"
- is-deflate "^1.0.0"
- is-gzip "^1.0.0"
- peek-stream "^1.1.0"
- pumpify "^1.3.3"
- through2 "^2.0.3"
-
gzip-size@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462"
@@ -11772,11 +11526,6 @@ human-signals@^2.1.0:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
-human-signals@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
- integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
-
humanize-ms@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/humanize-ms/-/humanize-ms-1.2.1.tgz#c46e3159a293f6b896da29316d8b6fe8bb79bbed"
@@ -11959,7 +11708,7 @@ ioredis@^5.3.2:
redis-parser "^3.0.0"
standard-as-callback "^2.1.0"
-ip@^2.0.0, ip@^2.0.1:
+ip@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.1.tgz#e8f3595d33a3ea66490204234b77636965307105"
integrity sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==
@@ -12109,12 +11858,7 @@ is-date-object@^1.0.1, is-date-object@^1.0.5:
dependencies:
has-tostringtag "^1.0.0"
-is-deflate@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-deflate/-/is-deflate-1.0.0.tgz#c862901c3c161fb09dac7cdc7e784f80e98f2f14"
- integrity sha512-YDoFpuZWu1VRXlsnlYMzKyVRITXj7Ej/V9gXQ2/pAe7X1J7M/RNOqaIYi6qUn+B7nGyB9pDXrv02dsB58d2ZAQ==
-
-is-docker@^2.0.0, is-docker@^2.1.1:
+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==
@@ -12155,11 +11899,6 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
dependencies:
is-extglob "^2.1.1"
-is-gzip@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-gzip/-/is-gzip-1.0.0.tgz#6ca8b07b99c77998025900e555ced8ed80879a83"
- integrity sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==
-
is-hex-prefixed@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554"
@@ -12173,11 +11912,6 @@ is-installed-globally@~0.4.0:
global-dirs "^3.0.0"
is-path-inside "^3.0.2"
-is-interactive@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e"
- integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==
-
is-map@^2.0.1, is-map@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127"
@@ -12257,13 +11991,6 @@ is-plain-object@5.0.0:
resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344"
integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==
-is-plain-object@^2.0.4:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677"
- integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==
- dependencies:
- isobject "^3.0.1"
-
is-potential-custom-element-name@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
@@ -12304,11 +12031,6 @@ is-stream@^2.0.0:
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077"
integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==
-is-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
- integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
-
is-string@^1.0.5, is-string@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
@@ -12392,11 +12114,6 @@ isexe@^2.0.0:
resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-isobject@^3.0.1:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df"
- integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==
-
isomorphic-unfetch@3.1.0, isomorphic-unfetch@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/isomorphic-unfetch/-/isomorphic-unfetch-3.1.0.tgz#87341d5f4f7b63843d468438128cb087b7c3e98f"
@@ -12989,32 +12706,6 @@ jsbn@~0.1.0:
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==
-jscodeshift@^0.15.1:
- version "0.15.2"
- resolved "https://registry.yarnpkg.com/jscodeshift/-/jscodeshift-0.15.2.tgz#145563860360b4819a558c75c545f39683e5a0be"
- integrity sha512-FquR7Okgmc4Sd0aEDwqho3rEiKR3BdvuG9jfdHjLJ6JQoWSMpavug3AoIfnfWhxFlf+5pzQh8qjqz0DWFrNQzA==
- dependencies:
- "@babel/core" "^7.23.0"
- "@babel/parser" "^7.23.0"
- "@babel/plugin-transform-class-properties" "^7.22.5"
- "@babel/plugin-transform-modules-commonjs" "^7.23.0"
- "@babel/plugin-transform-nullish-coalescing-operator" "^7.22.11"
- "@babel/plugin-transform-optional-chaining" "^7.23.0"
- "@babel/plugin-transform-private-methods" "^7.22.5"
- "@babel/preset-flow" "^7.22.15"
- "@babel/preset-typescript" "^7.23.0"
- "@babel/register" "^7.22.15"
- babel-core "^7.0.0-bridge.0"
- chalk "^4.1.2"
- flow-parser "0.*"
- graceful-fs "^4.2.4"
- micromatch "^4.0.4"
- neo-async "^2.5.0"
- node-dir "^0.1.17"
- recast "^0.23.3"
- temp "^0.8.4"
- write-file-atomic "^2.3.0"
-
jsdom@^20.0.0:
version "20.0.3"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db"
@@ -13216,7 +12907,7 @@ keyvaluestorage-interface@^1.0.0:
resolved "https://registry.yarnpkg.com/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz#13ebdf71f5284ad54be94bd1ad9ed79adad515ff"
integrity sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g==
-kind-of@^6.0.2, kind-of@^6.0.3:
+kind-of@^6.0.3:
version "6.0.3"
resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd"
integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==
@@ -13378,14 +13069,6 @@ loader-utils@^3.2.1:
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-3.2.1.tgz#4fb104b599daafd82ef3e1a41fb9265f87e1f576"
integrity sha512-ZvFw1KWS3GVyYBYb7qkmRM/WwL2TQQBxgCK62rlvm4WpVQ23Nb4tYjApUlfjrEGvOs7KHEsmyUn75OHZrJMWPw==
-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"
@@ -13462,7 +13145,7 @@ lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.7.0
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
-log-symbols@^4.0.0, log-symbols@^4.1.0:
+log-symbols@^4.0.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503"
integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==
@@ -13566,7 +13249,7 @@ magic-string@^0.30.5:
dependencies:
"@jridgewell/sourcemap-codec" "^1.4.15"
-make-dir@^2.0.0, make-dir@^2.1.0:
+make-dir@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5"
integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==
@@ -13723,7 +13406,7 @@ miller-rabin@^4.0.0:
bn.js "^4.0.0"
brorand "^1.0.1"
-mime-db@1.52.0, "mime-db@>= 1.43.0 < 2":
+mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
@@ -13750,11 +13433,6 @@ mimic-fn@^2.1.0:
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
-mimic-fn@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
- integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
-
mimic-response@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
@@ -13782,7 +13460,7 @@ minimatch@9.0.3:
dependencies:
brace-expansion "^2.0.1"
-minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
+minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -13817,37 +13495,17 @@ minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c"
integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==
-minipass@^3.0.0:
- version "3.3.6"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.6.tgz#7bba384db3a1520d18c9c0e5251c3444e95dd94a"
- integrity sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==
- dependencies:
- yallist "^4.0.0"
-
-minipass@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
- integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
-
"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4:
version "7.0.4"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==
-minizlib@^2.1.1:
- version "2.1.2"
- resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
- integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==
- dependencies:
- minipass "^3.0.0"
- yallist "^4.0.0"
-
mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
-mkdirp@^1.0.3, mkdirp@^1.0.4:
+mkdirp@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
@@ -14006,7 +13664,7 @@ negotiator@0.6.3:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
-neo-async@^2.5.0, neo-async@^2.6.2:
+neo-async@^2.6.2:
version "2.6.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f"
integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==
@@ -14084,14 +13742,7 @@ 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-dir@^0.1.17:
- version "0.1.17"
- resolved "https://registry.yarnpkg.com/node-dir/-/node-dir-0.1.17.tgz#5f5665d93351335caabef8f1c554516cf5f1e4e5"
- integrity sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==
- dependencies:
- minimatch "^3.0.2"
-
-node-fetch-native@^1.4.0, node-fetch-native@^1.4.1, node-fetch-native@^1.6.3:
+node-fetch-native@^1.4.0, node-fetch-native@^1.4.1:
version "1.6.4"
resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.4.tgz#679fc8fd8111266d47d7e72c379f1bed9acff06e"
integrity sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==
@@ -14193,13 +13844,6 @@ npm-run-path@^4.0.0, npm-run-path@^4.0.1:
dependencies:
path-key "^3.0.0"
-npm-run-path@^5.1.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f"
- integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==
- dependencies:
- path-key "^4.0.0"
-
nth-check@^2.0.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d"
@@ -14212,17 +13856,6 @@ nwsapi@^2.2.2:
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30"
integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==
-nypm@^0.3.8:
- version "0.3.8"
- resolved "https://registry.yarnpkg.com/nypm/-/nypm-0.3.8.tgz#a16b078b161be5885351e72cf0b97326973722bf"
- integrity sha512-IGWlC6So2xv6V4cIDmoV0SwwWx7zLG086gyqkyumteH2fIgCAM4nDVFB2iDRszDvmdSVW9xb1N+2KjQ6C7d4og==
- dependencies:
- citty "^0.1.6"
- consola "^3.2.3"
- execa "^8.0.1"
- pathe "^1.1.2"
- ufo "^1.4.0"
-
object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
@@ -14321,11 +13954,6 @@ ofetch@^1.3.3:
node-fetch-native "^1.4.0"
ufo "^1.3.0"
-ohash@^1.1.3:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/ohash/-/ohash-1.1.3.tgz#f12c3c50bfe7271ce3fd1097d42568122ccdcf07"
- integrity sha512-zuHHiGTYTA1sYJ/wZN+t5HKZaH23i4yI1HMwbuXm24Nid7Dv0KcuRlKoNKS9UNfAVSBlnGLcuQrnOKWOZoEGaw==
-
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"
@@ -14338,11 +13966,6 @@ on-finished@2.4.1:
dependencies:
ee-first "1.1.1"
-on-headers@~1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f"
- integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==
-
once@^1.3.0, once@^1.3.1, once@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -14357,22 +13980,6 @@ onetime@^5.1.0, onetime@^5.1.2:
dependencies:
mimic-fn "^2.1.0"
-onetime@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
- integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
- dependencies:
- mimic-fn "^4.0.0"
-
-open@^8.0.4, open@^8.4.0:
- version "8.4.2"
- resolved "https://registry.yarnpkg.com/open/-/open-8.4.2.tgz#5b5ffe2a8f793dcd2aad73e550cb87b59cb084f9"
- integrity sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==
- dependencies:
- define-lazy-prop "^2.0.0"
- is-docker "^2.1.1"
- is-wsl "^2.2.0"
-
opener@^1.5.2:
version "1.5.2"
resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.2.tgz#5d37e1f35077b9dcac4301372271afdeb2a13598"
@@ -14390,21 +13997,6 @@ optionator@^0.9.3:
prelude-ls "^1.2.1"
type-check "^0.4.0"
-ora@^5.4.1:
- version "5.4.1"
- resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18"
- integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==
- dependencies:
- bl "^4.1.0"
- chalk "^4.1.0"
- cli-cursor "^3.1.0"
- cli-spinners "^2.5.0"
- is-interactive "^1.0.0"
- is-unicode-supported "^0.1.0"
- log-symbols "^4.1.0"
- strip-ansi "^6.0.0"
- wcwidth "^1.0.1"
-
os-browserify@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"
@@ -14415,7 +14007,7 @@ ospath@^1.2.2:
resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b"
integrity sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==
-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==
@@ -14436,13 +14028,6 @@ p-limit@^4.0.0:
dependencies:
yocto-queue "^1.0.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"
@@ -14481,11 +14066,6 @@ p-try@^2.0.0:
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
-pako@~0.2.0:
- version "0.2.9"
- resolved "https://registry.yarnpkg.com/pako/-/pako-0.2.9.tgz#f3f7522f4ef782348da8161bad9ecfd51bf83a75"
- integrity sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==
-
pako@~1.0.5:
version "1.0.11"
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
@@ -14563,11 +14143,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"
@@ -14593,11 +14168,6 @@ path-key@^3.0.0, path-key@^3.1.0:
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-path-key@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
- integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
-
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
@@ -14621,7 +14191,7 @@ 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, pathe@^1.1.2:
+pathe@^1.1.0, pathe@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
@@ -14642,15 +14212,6 @@ pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.1.2:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
-peek-stream@^1.1.0:
- version "1.1.3"
- resolved "https://registry.yarnpkg.com/peek-stream/-/peek-stream-1.1.3.tgz#3b35d84b7ccbbd262fff31dc10da56856ead6d67"
- integrity sha512-FhJ+YbOSBb9/rIl2ZeE/QHEsWn7PqNYt8ARAY3kIgNGOk13g9FGyIY6JIl/xB/3TFRVoTv5as0l11weORrTekA==
- dependencies:
- buffer-from "^1.0.0"
- duplexify "^3.5.0"
- through2 "^2.0.3"
-
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
@@ -14733,7 +14294,7 @@ pino@7.11.0:
sonic-boom "^2.2.1"
thread-stream "^0.15.1"
-pirates@^4.0.4, pirates@^4.0.6:
+pirates@^4.0.4:
version "4.0.6"
resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.6.tgz#3018ae32ecfcff6c29ba2267cbf21166ac1f36b9"
integrity sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==
@@ -14745,13 +14306,6 @@ pixelmatch@^5.2.1:
dependencies:
pngjs "^6.0.0"
-pkg-dir@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3"
- integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==
- dependencies:
- find-up "^3.0.0"
-
pkg-dir@^4.1.0, pkg-dir@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3"
@@ -14927,11 +14481,6 @@ prettier@^2.3.1, prettier@^2.7.0:
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da"
integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==
-prettier@^3.1.1:
- version "3.2.5"
- resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368"
- integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==
-
pretty-bytes@^5.3.0, pretty-bytes@^5.4.1, pretty-bytes@^5.6.0:
version "5.6.0"
resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.6.0.tgz#356256f643804773c82f64723fe78c92c62beaeb"
@@ -14983,7 +14532,7 @@ process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
-prompts@^2.0.1, prompts@^2.4.0:
+prompts@^2.0.1:
version "2.4.2"
resolved "https://registry.yarnpkg.com/prompts/-/prompts-2.4.2.tgz#7b57e73b3a48029ad10ebd44f74b01722a4cb069"
integrity sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==
@@ -15100,14 +14649,6 @@ public-encrypt@^4.0.0:
randombytes "^2.0.1"
safe-buffer "^5.1.2"
-pump@^2.0.0:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909"
- integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==
- dependencies:
- end-of-stream "^1.1.0"
- once "^1.3.1"
-
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
@@ -15116,15 +14657,6 @@ pump@^3.0.0:
end-of-stream "^1.1.0"
once "^1.3.1"
-pumpify@^1.3.3:
- version "1.5.1"
- resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce"
- integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==
- dependencies:
- duplexify "^3.6.0"
- inherits "^2.0.3"
- pump "^2.0.0"
-
punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
@@ -15519,7 +15051,7 @@ read-pkg@^5.2.0:
parse-json "^5.0.0"
type-fest "^0.6.0"
-readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.3.8, readable-stream@~2.3.6:
+readable-stream@^2.0.2, readable-stream@^2.3.8, readable-stream@~2.3.6:
version "2.3.8"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b"
integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==
@@ -15583,7 +15115,7 @@ realistic-structured-clone@^3.0.0:
typeson "^6.1.0"
typeson-registry "^1.0.0-alpha.20"
-recast@^0.23.3, recast@^0.23.5:
+recast@^0.23.5:
version "0.23.6"
resolved "https://registry.yarnpkg.com/recast/-/recast-0.23.6.tgz#198fba74f66143a30acc81929302d214ce4e3bfa"
integrity sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==
@@ -15878,13 +15410,6 @@ rimraf@^3.0.0, rimraf@^3.0.2:
dependencies:
glob "^7.1.3"
-rimraf@~2.6.2:
- version "2.6.3"
- resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab"
- integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==
- dependencies:
- glob "^7.1.3"
-
ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c"
@@ -16034,16 +15559,16 @@ safe-array-concat@^1.1.0:
has-symbols "^1.0.3"
isarray "^2.0.5"
-safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
- version "5.1.2"
- resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
- integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
-
safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@^5.2.1, safe-buffer@~5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
+safe-buffer@~5.1.0, safe-buffer@~5.1.1:
+ version "5.1.2"
+ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
+ integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
+
safe-regex-test@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377"
@@ -16272,6 +15797,16 @@ serve-static@1.16.0:
parseurl "~1.3.3"
send "0.18.0"
+serve-static@1.16.2:
+ version "1.16.2"
+ resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296"
+ integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==
+ dependencies:
+ encodeurl "~2.0.0"
+ escape-html "~1.0.3"
+ parseurl "~1.3.3"
+ send "0.19.0"
+
set-blocking@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
@@ -16316,13 +15851,6 @@ sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8:
inherits "^2.0.1"
safe-buffer "^5.0.1"
-shallow-clone@^3.0.0:
- version "3.0.1"
- resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3"
- integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==
- dependencies:
- kind-of "^6.0.2"
-
sharp@^0.32.6:
version "0.32.6"
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.32.6.tgz#6ad30c0b7cd910df65d5f355f774aa4fce45732a"
@@ -16364,7 +15892,7 @@ signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
-signal-exit@^4.0.1, signal-exit@^4.1.0:
+signal-exit@^4.0.1:
version "4.1.0"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
@@ -16474,7 +16002,7 @@ source-map-support@0.5.13:
buffer-from "^1.0.0"
source-map "^0.6.0"
-source-map-support@^0.5.16, source-map-support@~0.5.20:
+source-map-support@~0.5.20:
version "0.5.21"
resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f"
integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==
@@ -16619,12 +16147,12 @@ store2@^2.14.2:
resolved "https://registry.yarnpkg.com/store2/-/store2-2.14.3.tgz#24077d7ba110711864e4f691d2af941ec533deb5"
integrity sha512-4QcZ+yx7nzEFiV4BMLnr/pRa5HYzNITX2ri0Zh6sT9EyQHbBHacC6YigllUPU9X3D0f/22QCgfokpKs52YRrUg==
-storybook@^8.0.6:
- version "8.0.6"
- resolved "https://registry.yarnpkg.com/storybook/-/storybook-8.0.6.tgz#8b2616030f94a9708c0771ed532a5cef09a421c2"
- integrity sha512-QcQl8Sj77scGl0s9pw+cSPFmXK9DPogEkOceG12B2PqdS23oGkaBt24292Y3W5TTMVNyHtRTRB/FqPwK3FOdmA==
+storybook@^8.3.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/storybook/-/storybook-8.3.0.tgz#172a5d5e415b83bcb08a3a670a2e6f34383dfea1"
+ integrity sha512-XKU+nem9OKX/juvJPwka1Q7DTpSbOe0IMp8ZyLQWorhFKpquJdUjryl7Z9GiFZyyTykCqH4ItQ7h8PaOmqVMOw==
dependencies:
- "@storybook/cli" "8.0.6"
+ "@storybook/core" "8.3.0"
stream-browserify@^3.0.0:
version "3.0.0"
@@ -16820,11 +16348,6 @@ strip-final-newline@^2.0.0:
resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad"
integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==
-strip-final-newline@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
- integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
-
strip-hex-prefix@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f"
@@ -16846,7 +16369,7 @@ strip-indent@^4.0.0:
dependencies:
min-indent "^1.0.1"
-strip-json-comments@^3.0.1, strip-json-comments@^3.1.1:
+strip-json-comments@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
@@ -16983,7 +16506,7 @@ tapable@^2.0.0, tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1:
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==
-tar-fs@^2.0.0, tar-fs@^2.1.1:
+tar-fs@^2.0.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==
@@ -17024,18 +16547,6 @@ tar-stream@^3.1.5:
fast-fifo "^1.2.0"
streamx "^2.15.0"
-tar@^6.2.0:
- version "6.2.1"
- resolved "https://registry.yarnpkg.com/tar/-/tar-6.2.1.tgz#717549c541bc3c2af15751bea94b1dd068d4b03a"
- integrity sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==
- dependencies:
- chownr "^2.0.0"
- fs-minipass "^2.0.0"
- minipass "^5.0.0"
- minizlib "^2.1.1"
- mkdirp "^1.0.3"
- yallist "^4.0.0"
-
telejson@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/telejson/-/telejson-7.2.0.tgz#3994f6c9a8f8d7f2dba9be2c7c5bbb447e876f32"
@@ -17048,13 +16559,6 @@ temp-dir@^2.0.0:
resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-2.0.0.tgz#bde92b05bdfeb1516e804c9c00ad45177f31321e"
integrity sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==
-temp@^0.8.4:
- version "0.8.4"
- resolved "https://registry.yarnpkg.com/temp/-/temp-0.8.4.tgz#8c97a33a4770072e0a05f919396c7665a7dd59f2"
- integrity sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==
- dependencies:
- rimraf "~2.6.2"
-
tempy@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tempy/-/tempy-0.6.0.tgz#65e2c35abc06f1124a97f387b08303442bde59f3"
@@ -17619,7 +17123,7 @@ 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, ufo@^1.3.2, ufo@^1.4.0:
+ufo@^1.3.0, ufo@^1.3.1, ufo@^1.3.2:
version "1.5.3"
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.3.tgz#3325bd3c977b6c6cd3160bf4ff52989adc9d3344"
integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==
@@ -18029,7 +17533,7 @@ warning@^4.0.3:
dependencies:
loose-envify "^1.0.0"
-watchpack@^2.2.0, watchpack@^2.4.1:
+watchpack@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.1.tgz#29308f2cac150fa8e4c92f90e0ec954a9fed7fff"
integrity sha512-8wrBCMtVhqcXP2Sup1ctSkga6uc2Bx0IIvKyT7yTFier5AXHooSI+QyQQAtTb7+E0IUCCKyTFmXqdqgum2XWGg==
@@ -18037,13 +17541,6 @@ watchpack@^2.2.0, watchpack@^2.4.1:
glob-to-regexp "^0.4.1"
graceful-fs "^4.1.2"
-wcwidth@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
- integrity sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==
- dependencies:
- defaults "^1.0.3"
-
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
@@ -18511,15 +18008,6 @@ wrappy@1:
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
-write-file-atomic@^2.3.0:
- version "2.4.3"
- resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.3.tgz#1fd2e9ae1df3e75b8d8c367443c692d4ca81f481"
- integrity sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==
- dependencies:
- graceful-fs "^4.1.11"
- imurmurhash "^0.1.4"
- signal-exit "^3.0.2"
-
write-file-atomic@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.2.tgz#a9df01ae5b77858a027fd2e80768ee433555fcfd"
From 89675446f7be45ce5d9152f265cdfd786d6d84ef Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Cl=C3=B3vis=20Neto?=
Date: Mon, 16 Sep 2024 12:41:36 +0200
Subject: [PATCH 75/81] Fix: back button breakpoint in tx flow (#4181)
* fix: adjust media query breakpoint of the back button in the modal screens
* fix: use mui 'lg' breakpoint property instead of magic number
---
src/components/tx-flow/common/TxLayout/index.tsx | 2 +-
src/components/tx-flow/common/TxLayout/styles.module.css | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/tx-flow/common/TxLayout/index.tsx b/src/components/tx-flow/common/TxLayout/index.tsx
index e3f1dc6b6b..de243b6d85 100644
--- a/src/components/tx-flow/common/TxLayout/index.tsx
+++ b/src/components/tx-flow/common/TxLayout/index.tsx
@@ -83,7 +83,7 @@ const TxLayout = ({
const theme = useTheme()
const isSmallScreen = useMediaQuery(theme.breakpoints.down('md'))
- const isDesktop = useMediaQuery(theme.breakpoints.down(1399.95))
+ const isDesktop = useMediaQuery(theme.breakpoints.down('lg'))
const steps = Array.isArray(children) ? children : [children]
const progress = Math.round(((step + 1) / steps.length) * 100)
diff --git a/src/components/tx-flow/common/TxLayout/styles.module.css b/src/components/tx-flow/common/TxLayout/styles.module.css
index 03b06e83ca..5344a505cb 100644
--- a/src/components/tx-flow/common/TxLayout/styles.module.css
+++ b/src/components/tx-flow/common/TxLayout/styles.module.css
@@ -108,7 +108,7 @@
/* Height of transaction type title */
margin-top: 46px;
}
-@media (max-width: 1399.95px) {
+@media (max-width: 1199px) {
.backButton {
left: 50%;
transform: translateX(-50%);
From 43c7da0406667c7ece227a4ad24c89cedc94d374 Mon Sep 17 00:00:00 2001
From: Michael <30682308+mike10ca@users.noreply.github.com>
Date: Mon, 16 Sep 2024 11:40:50 +0200
Subject: [PATCH 76/81] Tests: Remove duplicate tests (#4179)
---
cypress/e2e/prodhealthcheck/load_safe.cy.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cypress/e2e/prodhealthcheck/load_safe.cy.js b/cypress/e2e/prodhealthcheck/load_safe.cy.js
index c9e78740ca..a04a88c235 100644
--- a/cypress/e2e/prodhealthcheck/load_safe.cy.js
+++ b/cypress/e2e/prodhealthcheck/load_safe.cy.js
@@ -21,7 +21,7 @@ const INVALID_ADDRESS_ERROR_MSG = 'Address given is not a valid Safe address'
const OWNER_ENS_DEFAULT_NAME = 'test20.eth'
const OWNER_ADDRESS = constants.EOA
-describe('Load Safe tests', () => {
+describe('[PROD] Load Safe tests', () => {
before(async () => {
staticSafes = await getSafes(CATEGORIES.static)
})
From 683b2dfb593ac1331c5604b77d87e3f2e41ac1e9 Mon Sep 17 00:00:00 2001
From: Manuel Gellfart
Date: Mon, 16 Sep 2024 12:55:47 +0200
Subject: [PATCH 77/81] fix: do not check network for confirm / execute buttons
in the queue (#4182)
---
src/components/transactions/ExecuteTxButton/index.tsx | 2 +-
src/components/transactions/SignTxButton/index.tsx | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/components/transactions/ExecuteTxButton/index.tsx b/src/components/transactions/ExecuteTxButton/index.tsx
index ce16c0aa3f..57ce073958 100644
--- a/src/components/transactions/ExecuteTxButton/index.tsx
+++ b/src/components/transactions/ExecuteTxButton/index.tsx
@@ -50,7 +50,7 @@ const ExecuteTxButton = ({
return (
<>
-
+
{(isOk) => (
diff --git a/src/components/transactions/SignTxButton/index.tsx b/src/components/transactions/SignTxButton/index.tsx
index 442cbe26a3..76298771c5 100644
--- a/src/components/transactions/SignTxButton/index.tsx
+++ b/src/components/transactions/SignTxButton/index.tsx
@@ -34,7 +34,7 @@ const SignTxButton = ({
}
return (
-
+
{(isOk) => (
From 6ff1680c3f4cf97a364aca1e7f326df810b4f5dd Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Mon, 16 Sep 2024 16:03:23 +0200
Subject: [PATCH 78/81] Docs: update README.md (#4184)
Add some general info about Safe Wallet
---
README.md | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/README.md b/README.md
index 4ca7cf6970..f890fa7578 100644
--- a/README.md
+++ b/README.md
@@ -5,7 +5,9 @@
![GitHub package.json version (branch)](https://img.shields.io/github/package-json/v/safe-global/safe-wallet-web)
[![GitPOAP Badge](https://public-api.gitpoap.io/v1/repo/safe-global/safe-wallet-web/badge)](https://www.gitpoap.io/gh/safe-global/safe-wallet-web)
-The default Safe web interface.
+Safe{Wallet} is a smart contract wallet for Ethereum and other EVM chains. Based on Gnosis Safe multisig contracts.
+
+This repository is the frontend of the Safe{Wallet} app.
## Contributing
From 5d8992c7554da071cedc8f4e3fa9b0ea10d80c80 Mon Sep 17 00:00:00 2001
From: katspaugh <381895+katspaugh@users.noreply.github.com>
Date: Mon, 16 Sep 2024 16:06:03 +0200
Subject: [PATCH 79/81] Legal: update the terms page [SW-185] (#4178)
* Legal: update the terms page
* August -> September
---
.../common/CookieAndTermBanner/index.tsx | 7 +-
src/pages/terms.tsx | 204 +++++++++---------
src/store/cookiesAndTermsSlice.ts | 2 +-
3 files changed, 108 insertions(+), 105 deletions(-)
diff --git a/src/components/common/CookieAndTermBanner/index.tsx b/src/components/common/CookieAndTermBanner/index.tsx
index b9b6a5fbb1..43dfe6ca1c 100644
--- a/src/components/common/CookieAndTermBanner/index.tsx
+++ b/src/components/common/CookieAndTermBanner/index.tsx
@@ -75,9 +75,10 @@ export const CookieAndTermBanner = ({
By browsing this page, you accept our{' '}
- Terms & Conditions (last updated August 2024) and the
- use of necessary cookies. By clicking "Accept all" you additionally agree to the use of Beamer
- and Analytics cookies as listed below. Cookie policy
+ Terms & Conditions (last updated September 2024) and
+ the use of necessary cookies. By clicking "Accept all" you additionally agree to the use of
+ Beamer and Analytics cookies as listed below.{' '}
+ Cookie policy
diff --git a/src/pages/terms.tsx b/src/pages/terms.tsx
index 9a1d3b629a..da1777cca0 100644
--- a/src/pages/terms.tsx
+++ b/src/pages/terms.tsx
@@ -12,7 +12,7 @@ const SafeTerms = () => (
Terms and Conditions
- Last updated: August 2024.
+ Last updated: September 2024.
1. What is the scope of the Terms?
@@ -38,11 +38,8 @@ const SafeTerms = () => (
We reserve the right to change these Terms at any time and without giving reasons, while considering and
- weighing your interests. The new Terms will be communicated to you in advance. They are considered as agreed
- upon if you do not object to their validity within 14 days after receipt of the notification. We will separately
- inform you about the essential changes, the possibility to object, the deadline and the consequences of
- inactivity. If you object, the current version of the Terms remains applicable. Our right to terminate the
- contract according to Clause 13 remains unaffected.
+ weighing your interests. The new Terms will be communicated to you in advance. If you do not accept the new
+ Terms, you are no longer entitled to use the Services.
@@ -111,31 +108,32 @@ const SafeTerms = () => (
WalletConnect.
- “Safe App”
+ {'“Safe{Wallet} App”'}
You may access Safe Accounts using the {'Safe{Wallet}'} web app, mobile app for iOS and android, or the browser
- extension (each a “Safe App”). The Safe App may be used to manage your personal digital assets on
- Ethereum and other common EVM chains when you connect a Safe Account with third-party services (as defined
- below). The Safe App provides certain features that may be amended from time to time.{' '}
+ extension (each a {'“Safe{Wallet} App”'}). The {'Safe{Wallet}'} App may be used to manage your personal
+ digital assets on Ethereum and other common EVM chains when you connect a Safe Account with
+ third-party services (as defined below). The {'Safe{Wallet}'} App provides certain features that may be
+ amended from time to time.{' '}
“Third-Party Safe Apps”
- The Safe App allows you to connect Safe Accounts to third-party decentralized applications
+ The {'Safe{Wallet}'} App allows you to connect Safe Accounts to third-party applications
(“Third-Party Safe Apps”) and use third-party services such as from the decentralized
- finance sector, DAO Tools or services related to NFTs (“Third-Party Services"). The
- Third-Party Safe Apps are integrated in the user interface of the Safe App via inline framing. The provider
- of the Third-Party Safe App and related Third-Party Service is responsible for the operation of the service
- and the correctness, completeness and actuality of any information provided therein. We make a pre-selection of
- Third-Party Safe Apps that we show in the Safe App. However, we only perform a rough triage in advance for
- obvious problems and functionality in terms of loading time and resolution capability of the transactions.
- Accordingly, in the event of any (technical) issues concerning the Third-Party Services, the user must only
- contact the respective service provider directly. The terms of service, if any, shall be governed by the
- applicable contractual provisions between the User and the respective provider of the Third-Party Service.
- Accordingly, we are not liable in the event of a breach of contract, damage or loss related to the use of such
- Third-Party Service.
+ finance sector, DAO tools or services related to NFTs (“Third-Party Services"). The
+ Third-Party Safe Apps are integrated in the user interface of the {'Safe{Wallet}'} App via inline framing.
+ The provider of the Third-Party Safe App and/or related Third-Party Services is responsible for the operation
+ of the service and the correctness, completeness and actuality of any information provided therein. We make a
+ pre-selection of Third-Party Safe Apps that we show in the {'Safe{Wallet}'} App. However, we only perform a
+ rough triage in advance for obvious problems and functionality in terms of loading time and resolution capability
+ of the transactions. Accordingly, in the event of any (technical) issues concerning the Third-Party Services, the
+ user must only contact the respective service provider directly. The terms of service, if any, shall be governed
+ by the applicable contractual provisions between the User and the respective provider of the Third-Party Safe Apps
+ or Third-Party Services. Accordingly, we are not liable in the event of a breach of contract, damage or loss
+ related to the use of such Third-Party Safe Apps or Third-Party Services.
4. What do the Services not consist of?
@@ -169,7 +167,7 @@ const SafeTerms = () => (
issuance of the Safe Token and any related functionalities or reward programs.
- 5. What do you need to know about Third-Party Services?
+ 5. What do you need to know about Third-Party Safe Apps and Third-Party Services?
We provide you the possibility to interact with your Safe Account through Third-Party Services. Any
@@ -187,29 +185,29 @@ const SafeTerms = () => (
- We do not have any oversight over your activities with Third-Party Services especially by using
+ We do not have any oversight over your activities with Third-Party Services especially by using
Third-Party Safe Apps, and therefore we do not and cannot make any representation regarding their
appropriateness and suitability for you.
- Third-Party Services are not hosted, owned, controlled or maintained by us. We also do not participate in
- the Transaction and will not and cannot monitor, verify, censor or edit the functioning or content of any
- Third-Party Service.
+ Third-Party Safe Apps and Third-Party Services are not hosted, owned, controlled or maintained by us. We also do
+ not participate in the Transaction and will not and cannot monitor, verify, censor or edit the functioning or
+ content of any Third-Party Safe Apps and Third-Party Services.
We have not conducted any security audit, bug bounty or formal verification (whether internal or external) of
- the Third-Party Services.
+ the Third-Party Safe Apps and Third-Party Services.
We have no control over, do not recommend, endorse, or otherwise take a position on the integrity, functioning
- of, content and your use of Third-Party Services, whose sole responsibility lies with the person from whom
- such services or content originated.
+ of, content and your use of Third-Party Safe Apps and Third-Party Services, whose sole responsibility lies with
+ the person from whom such services or content originated.
- When you access or use Third-Party Services you accept that there are risks in doing so and that you alone
- assume any such risks when choosing to interact with them. We are not liable for any errors or omissions or for
- any damages or loss you might suffer through interacting with those Third-Party Services, such as
- Third-Party Safe Apps.
+ When you access or use Third-Party Safe Apps and Third-Party Services you accept that there are risks in doing
+ so and that you alone assume any such risks when choosing to interact with them. We are not liable for any
+ errors or omissions or for any damages or loss you might suffer through interacting with those Third-Party Safe
+ Apps and Third-Party Services.
You know of the inherent risks of cryptographic and Blockchain-based systems and the high volatility of Token
@@ -217,37 +215,39 @@ const SafeTerms = () => (
to refund Token that have been deployed.
- You should read the license requirements, terms and conditions as well as privacy policy of each
- Third-Party Service that you access or use. Certain Third-Party Services may involve complex
- Transactions that entail a high degree of risk.
+ You should read the license requirements, terms and conditions as well as privacy policy of each Third-Party
+ Safe App and Third-Party Service that you access or use. Certain Third-Party Safe Apps and Third-Party Services
+ may involve complex Transactions that entail a high degree of risk.
- If you contribute integrations to Third-Party Services, you are responsible for all content you contribute,
- in any manner, and you must have all rights necessary to do so, in the manner in which you contribute it. You
- are responsible for all your activity in connection with any such Third-Party Service.{' '}
+ If you contribute integrations to Third-Party Safe Apps and Third-Party Services, you are responsible for all
+ content you contribute, in any manner, and you must have all rights necessary to do so, in the manner in which
+ you contribute it. You are responsible for all your activity in connection with any such Third-Party Safe Apps
+ and Third-Party Services.
- Your interactions with persons found on or through the Third-Party Service, including payment and delivery
- of goods and services, financial transactions, and any other terms associated with such dealings, are solely
- between you and such persons. You agree that we shall not be responsible or liable for any loss or damage of any
- sort incurred as the result of any such dealings.
+ Your interactions with persons found on or through the Third-Party Safe Apps and Third-Party Services, including
+ payment and delivery of goods and services, financial transactions, and any other terms associated with such
+ dealings, are solely between you and such persons. You agree that we shall not be responsible or liable for any
+ loss or damage of any sort incurred as the result of any such dealings.
- If there is a dispute between you and the Third-Party Service provider or/and other users of the
- Third-Party Service, you agree that we are under no obligation to become involved. In the event that you
- have a dispute with one or more other users, you release us, our officers, employees, agents, contractors and
- successors from claims, demands, and damages of every kind or nature, known or unknown, suspected or
- unsuspected, disclosed or undisclosed, arising out of or in any way related to such disputes and/or our
- Services.
+ If there is a dispute between you and the Third-Party Safe Apps or Third-Party Services provider or/and other
+ users of the Third-Party Safe Apps and Third-Party Services, you agree that we are under no obligation to become
+ involved. In the event that you have a dispute with one or more other users, you release us, our officers,
+ employees, agents, contractors and successors from claims, demands, and damages of every kind or nature, known
+ or unknown, suspected or unsuspected, disclosed or undisclosed, arising out of or in any way related to such
+ disputes and/or our Services.
6. What are the fees for the Services?
- The use of the Safe App or Third-Party Safe Apps may cause fees, including network fees, as indicated in
- the respective app. CC has no control over the fees charged by the Third-Party Services. CC may change its own
- fees at any time. Price changes will be communicated to the User in due time before taking effect.
+ The use of the {'Safe{Wallet}'} App, Third-Party Safe Apps or Third-Party Services may cause fees, including
+ network fees, as indicated in the respective app. CC has no control over the fees charged by the Third-Party
+ Safe Apps or Third-Party Services. CC may change its own fees at any time. Price changes will be communicated to
+ the User in due time before taking effect.
The User is only entitled to offset and/or assert rights of retention if his counterclaims are legally
@@ -277,14 +277,14 @@ const SafeTerms = () => (
We shall not be responsible for recovering your Safe Account.
You are solely responsible for securing a back-up of your Safe Account access as you see fit.
- Any recovery feature we provide access to within the Safe App is a mechanism controlled by your Safe Account on
- the Blockchain, both of which we don't have any influence over once you have set it up. We will never act
- as a recoverer ourselves and don't offer recovery services. The Self Custodial Recovery feature allows you
- to determine your own recovery setup and nominate anyone including yourself as your recoverer. The recoverer can
- start the recovery process at any time. Please note that we are not responsible for notifying you of this
- process (see Section 7 above). Furthermore we reserve the right to cease the access to the Self Custodial
- Recovery feature via our Safe App taking the user's reasonable interests into account and providing due
- notification.
+ Any recovery feature we provide access to within the {'Safe{Wallet}'} App is a mechanism controlled by your Safe
+ Account on the Blockchain, both of which we don't have any influence over once you have set it up. We will
+ never act as a recoverer ourselves and don't offer recovery services. The Self Custodial Recovery feature
+ allows you to determine your own recovery setup and nominate anyone including yourself as your recoverer. The
+ recoverer can start the recovery process at any time. Please note that we are not responsible for notifying you
+ of this process (see Section 7 above). Furthermore we reserve the right to cease the access to the Self
+ Custodial Recovery feature via our {'Safe{Wallet}'} App taking the user's reasonable interests into account
+ and providing due notification.
The recovery feature is provided free of charge and liability is limited pursuant to Section 18 below.
@@ -297,7 +297,7 @@ const SafeTerms = () => (
You are responsible for monitoring Safe Account as you see fit.
- Any notification service we provide or offer for subscription within the Safe App via e-mail or push
+ Any notification service we provide or offer for subscription within the {'Safe{Wallet}'} App via e-mail or push
notifications or any other means of communication is provided free of charge and liability is limited pursuant
to Section 18 below. Furthermore we reserve the right to change the notification feature from time to time or
cease to provide them without notice.
@@ -306,15 +306,15 @@ const SafeTerms = () => (
10. Are we responsible for flagging malicious transactions?
- We shall not be responsible for flagging malicious transactions in our Safe App.
+ We shall not be responsible for flagging malicious transactions in our {'Safe{Wallet}'} App.
You are solely responsible for checking any transaction, address, Token or other item you interact with via your
- Smart Account in our Safe App.
+ Smart Account in our {'Safe{Wallet}'} App.
- Any security flagging or warning service we provide or offer for subscription within the Safe App is provided
- free of charge and liability is limited pursuant to Section 18 below. Furthermore we reserve the right to change
- the feature from time to time or cease to provide them without notice.
+ Any security flagging or warning service we provide or offer for subscription within the {'Safe{Wallet}'} App is
+ provided free of charge and liability is limited pursuant to Section 18 below. Furthermore we reserve the right
+ to change the feature from time to time or cease to provide them without notice.
@@ -343,9 +343,10 @@ const SafeTerms = () => (
You may view, have access to, and use third-party content and services, for example widget integrations, within
- the Safe App (“Third-Party Features”). You view, access, or use Third-Party Features at your own election. Your
- reliance on Third-Party Features is subject to separate terms and conditions set forth by the applicable third
- party content and/or service provider (“Third-Party Terms”). Third-Party Terms may, amongst other things,
+ the {'Safe{Wallet}'} App (“Third-Party Features”). You view, access, or use Third-Party Features at your own
+ election. Your reliance on Third-Party Features is subject to separate terms and conditions set forth by the
+ applicable third party content and/or service provider (“Third-Party Terms”). Third-Party Terms may, amongst
+ other things,
involve separate fees and charges,
include disclaimers or risk warnings,
@@ -357,26 +358,27 @@ const SafeTerms = () => (
Features.{' '}
- If we offer access to Third-Party Features in the Safe App free of charge by us (Third-Parties may charge
- separate fees), the liability for providing access to such Third-Party Feature is limited pursuant to Section 18
- below. Furthermore we reserve the right to cease to provide access to those Third-Party Features through the
- Safe App without notice.
+ If we offer access to Third-Party Features in the {'Safe{Wallet}'} App free of charge by us (Third-Parties may
+ charge separate fees), the liability for providing access to such Third-Party Feature is limited pursuant to
+ Section 18 below. Furthermore we reserve the right to cease to provide access to those Third-Party Features
+ through the
+ {'Safe{Wallet}'} App without notice.
13. Can we terminate or limit your right to use our Services?
- We may cease offering our Services and/or terminate the Agreement and refuse access to the Safe Apps at any
- time. The right of the parties to terminate the Agreement at any time for cause remains unaffected. In case of
- our termination of the Agreement, you may no longer access your Safe Account via our Services. However, you may
- continue to access your Safe Account and any Tokens via a third-party wallet provider using your Recovery Phrase
- and Private Keys.
+ We may cease offering our Services and/or terminate the Agreement and refuse access to the {'Safe{Wallet}'} App
+ at any time. The right of the parties to terminate the Agreement at any time for cause remains unaffected. In
+ case of our termination of the Agreement, you may no longer access your Safe Account via our Services. However,
+ you may continue to access your Safe Account and any Tokens via a third-party wallet provider using your
+ Recovery Phrase and Private Keys.
- We reserve the right to limit the use of the Safe Apps to a specified number of Users if necessary to protect or
- ensure the stability and integrity of the Services. We will only be able to limit access to the Services. At no
- time will we be able to limit or block access to or transfer your funds without your consent.
+ We reserve the right to limit the use of the {'Safe{Wallet}'} App to a specified number of Users if necessary to
+ protect or ensure the stability and integrity of the Services. We will only be able to limit access to the
+ Services. At no time will we be able to limit or block access to or transfer your funds without your consent.
@@ -388,8 +390,8 @@ const SafeTerms = () => (
All intellectual property rights in Safe Accounts and the Services throughout the world belong to us as owner or
our licensors. Nothing in these Terms gives you any rights in respect of any intellectual property owned by us
- or our licensors and you acknowledge that you do not acquire any ownership rights by downloading the Safe App or
- any content from the Safe App.
+ or our licensors and you acknowledge that you do not acquire any ownership rights by downloading the{' '}
+ {'Safe{Wallet}'} App or any content from the {'Safe{Wallet}'} App.
If you are a consumer we grant you a simple, limited license, but do not sell, to you the Services you download
@@ -405,8 +407,8 @@ const SafeTerms = () => (
or non-infringement.{' '}
- If you use the Safe App via web browser, the strict liability of CC for damages (sec. 536a German Civil Code)
- for defects existing at the time of conclusion of the contract is precluded.{' '}
+ If you use the {'Safe{Wallet}'} App via web browser, the strict liability of CC for damages (sec. 536a German
+ Civil Code) for defects existing at the time of conclusion of the contract is precluded.{' '}
The foregoing provisions will not limit CC’s liability as defined in Clause 18.
@@ -487,21 +489,21 @@ const SafeTerms = () => (
18. What about our liability to you?
- If the Safe App or Services are provided to the User free of charge (please note, in this context, that any
- service, network, and/or transaction fees may be charged by third parties via the Blockchain and not necessarily
- by us), CC shall be liable only in cases of intent, gross negligence, or if CC has fraudulently concealed a
- possible material or legal defect of the Safe App or Services.
-
-
- If the Safe App or Services are not provided to the User free of charge, CC shall be liable only (i) in cases
- pursuant to Clause 18.1 as well as (ii) in cases of simple negligence for damages resulting from the breach of
- an essential contractual duty, a duty, the performance of which enables the proper execution of this Agreement
- in the first place and on the compliance of which the User regularly relies and may rely, whereby CC's
- liability shall be limited to the compensation of the foreseeable, typically occurring damage. The Parties agree
- that the typical foreseeable damage equals the sum of the annual Fees paid or agreed to be paid by the User to
- CC during the course of the calendar year in which the event giving rise to the damage claim occurred. Liability
- in cases of simple negligence for damages resulting from the breach of a non-essential contractual duty are
- excluded.{' '}
+ If the {'Safe{Wallet}'} App or Services are provided to the User free of charge (please note, in this context,
+ that any service, network, and/or transaction fees may be charged by third parties via the Blockchain and not
+ necessarily by us), CC shall be liable only in cases of intent, gross negligence, or if CC has fraudulently
+ concealed a possible material or legal defect of the {'Safe{Wallet}'} App or Services.
+
+
+ If the {'Safe{Wallet}'} App or Services are not provided to the User free of charge, CC shall be liable only (i)
+ in cases pursuant to Clause 18.1 as well as (ii) in cases of simple negligence for damages resulting from the
+ breach of an essential contractual duty, a duty, the performance of which enables the proper execution of this
+ Agreement in the first place and on the compliance of which the User regularly relies and may rely, whereby
+ CC's liability shall be limited to the compensation of the foreseeable, typically occurring damage. The
+ Parties agree that the typical foreseeable damage equals the sum of the annual Fees paid or agreed to be paid by
+ the User to CC during the course of the calendar year in which the event giving rise to the damage claim
+ occurred. Liability in cases of simple negligence for damages resulting from the breach of a non-essential
+ contractual duty are excluded.{' '}
The limitations of liability according to Clause 18.1 and Clause 18.2 do not apply (i) to damages resulting from
diff --git a/src/store/cookiesAndTermsSlice.ts b/src/store/cookiesAndTermsSlice.ts
index b63d31fd07..d8edbc46f4 100644
--- a/src/store/cookiesAndTermsSlice.ts
+++ b/src/store/cookiesAndTermsSlice.ts
@@ -19,7 +19,7 @@ const initialState: CookiesAndTermsState = {
}
export const cookiesAndTermsSlice = createSlice({
- name: 'cookies_terms_v1.1',
+ name: 'cookies_terms_v1.2',
initialState,
reducers: {
saveCookieAndTermConsent: (_, { payload }: PayloadAction) => payload,
From cb349b978306c187df99441560117073db04f7a6 Mon Sep 17 00:00:00 2001
From: James Mealy
Date: Tue, 17 Sep 2024 13:10:20 +0200
Subject: [PATCH 80/81] fix: add network switch warning to recovery execution
(#4187)
---
.../recovery/components/ExecuteRecoveryButton/index.tsx | 8 +++++++-
.../recovery/components/RecoverySigners/index.tsx | 3 +++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/features/recovery/components/ExecuteRecoveryButton/index.tsx b/src/features/recovery/components/ExecuteRecoveryButton/index.tsx
index 0112139dd7..a5d6e63bcd 100644
--- a/src/features/recovery/components/ExecuteRecoveryButton/index.tsx
+++ b/src/features/recovery/components/ExecuteRecoveryButton/index.tsx
@@ -12,6 +12,8 @@ import { Errors, trackError } from '@/services/exceptions'
import { asError } from '@/services/exceptions/utils'
import { RecoveryListItemContext } from '../RecoveryListItem/RecoveryListItemContext'
import type { RecoveryQueueItem } from '@/features/recovery/services/recovery-state'
+import useIsWrongChain from '@/hooks/useIsWrongChain'
+import { useCurrentChain } from '@/hooks/useChains'
export function ExecuteRecoveryButton({
recovery,
@@ -26,6 +28,8 @@ export function ExecuteRecoveryButton({
const wallet = useWallet()
const { safe } = useSafeInfo()
const isDisabled = !isExecutable || isPending
+ const isWrongChain = useIsWrongChain()
+ const chain = useCurrentChain()
const onClick = async (e: SyntheticEvent) => {
e.stopPropagation()
@@ -58,7 +62,9 @@ export function ExecuteRecoveryButton({
}
+
+
From 389633eec06302cbc53592c31814aa5b445258a6 Mon Sep 17 00:00:00 2001
From: katspaugh
Date: Tue, 17 Sep 2024 14:31:27 +0200
Subject: [PATCH 81/81] 1.43.0
---
package.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/package.json b/package.json
index e25226eff5..3030aab4af 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "safe-wallet-web",
"homepage": "https://github.com/safe-global/safe-wallet-web",
"license": "GPL-3.0",
- "version": "1.42.0",
+ "version": "1.43.0",
"type": "module",
"scripts": {
"dev": "next dev",