diff --git a/e2e/fixtures/swap/helpers/checkTokenDropdown.ts b/e2e/fixtures/swap/helpers/checkTokenDropdown.ts
index a02e60e2..c3e9174a 100644
--- a/e2e/fixtures/swap/helpers/checkTokenDropdown.ts
+++ b/e2e/fixtures/swap/helpers/checkTokenDropdown.ts
@@ -10,10 +10,10 @@ export const createCheckTokenDropdown: Wrapper = ({ page, element }) => (
await page.waitForLoadState('networkidle')
- await element.checkVisibility({ testId: 'token-select-input' })
- await element.checkVisibility({ testId: 'token-select-option-USDT' })
+ await element.checkVisibility({ testId: 'amount-input-input' })
+ await element.checkVisibility({ testId: 'amount-input-option-USDT' })
- await page.getByTestId('token-select-option-USDT').click()
+ await page.getByTestId('amount-input-option-USDT').click()
await element.checkText({ testId: 'amount-input-token', expectedText: 'USDT' })
@@ -21,11 +21,11 @@ export const createCheckTokenDropdown: Wrapper = ({ page, element }) => (
await page.waitForLoadState('networkidle')
- await page.getByTestId('token-select-input').fill(stakeToken)
+ await page.getByTestId('amount-input-input').fill(stakeToken)
- await element.checkVisibility({ testId: `token-select-option-${stakeToken}` })
- await element.checkVisibility({ testId: 'token-select-option-USDT', isVisible: false })
+ await element.checkVisibility({ testId: `amount-input-option-${stakeToken}` })
+ await element.checkVisibility({ testId: 'amount-input-option-USDT', isVisible: false })
- await page.getByTestId(`token-select-option-${stakeToken}`).click()
+ await page.getByTestId(`amount-input-option-${stakeToken}`).click()
}
)
diff --git a/e2e/fixtures/vault/setVaultData.ts b/e2e/fixtures/vault/setVaultData.ts
index 27586978..873f348b 100644
--- a/e2e/fixtures/vault/setVaultData.ts
+++ b/e2e/fixtures/vault/setVaultData.ts
@@ -79,6 +79,7 @@ export const createSetVaultData: Wrapper = ({ page }) => (
},
isPostPectra: true,
protocolFeePercent: String(feePercent / 100),
+ avgQueueDays: 1,
}
await page.addInitScript((payload) => {
diff --git a/e2e/tests/stake.spec.ts b/e2e/tests/stake.spec.ts
index 3c41217f..07cb671a 100644
--- a/e2e/tests/stake.spec.ts
+++ b/e2e/tests/stake.spec.ts
@@ -114,7 +114,7 @@ test('Stake info', async ({ swap, wallet }) => {
expect(parseFloat(assetPrev)).toEqual(0)
expect(parseFloat(assetNext)).toEqual(value)
- expect(Number(gas.replace('$ ' , ''))).toBeGreaterThan(0)
+ expect(Number(gas.replace('$' , ''))).toBeGreaterThan(0)
})
test('Stake', async ({ wallet, swap }) => {
diff --git a/package.json b/package.json
index 4d1c9bc1..84a57296 100644
--- a/package.json
+++ b/package.json
@@ -76,6 +76,7 @@
"dependencies": {
"@binance/w3w-ethereum-provider": "1.1.8-alpha.0",
"@cowprotocol/cow-sdk": "7.2.5",
+ "@cowprotocol/sdk-ethers-v6-adapter": "0.3.0",
"@floating-ui/react": "0.27.16",
"@floating-ui/react-dom": "2.1.6",
"@headlessui/react": "2.2.4",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 5b8e5e4a..851f1a85 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -18,6 +18,9 @@ importers:
'@cowprotocol/cow-sdk':
specifier: 7.2.5
version: 7.2.5(ajv@8.17.1)(cross-fetch@3.2.0)(ipfs-only-hash@4.0.0)(multiformats@9.9.0)
+ '@cowprotocol/sdk-ethers-v6-adapter':
+ specifier: 0.3.0
+ version: 0.3.0(ethers@6.14.3)
'@floating-ui/react':
specifier: 0.27.16
version: 0.27.16(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
@@ -370,6 +373,11 @@ packages:
'@cowprotocol/sdk-contracts-ts@0.8.1':
resolution: {integrity: sha512-8yQO11S4R3mAfgKqb5afCo9c+z/sHpKiOZuN+gry46fjBKK3kUd2hKLWNYnQds5xUVJ07DlT0k7jFGgkEnremw==}
+ '@cowprotocol/sdk-ethers-v6-adapter@0.3.0':
+ resolution: {integrity: sha512-1TXtTLB5Zi2MGbCvEB9az0fJL1RDmQOa9sohO3biQNP/crGDb6jwPv30RtR3Sr621Dy8HNrfnJFHC87klPXC2g==}
+ peerDependencies:
+ ethers: ^6.13.7
+
'@cowprotocol/sdk-order-book@0.4.4':
resolution: {integrity: sha512-iTP2Vfi9h4ACvTnRArA0s3BmJgnUnNcQfsdMva4udkLy1GwjQgju7FkcCmlUxPaPvFgGm9hz8E9yPuNMWp/xWg==}
@@ -5656,6 +5664,11 @@ snapshots:
'@cowprotocol/sdk-common': 0.4.0
'@cowprotocol/sdk-config': 0.6.2
+ '@cowprotocol/sdk-ethers-v6-adapter@0.3.0(ethers@6.14.3)':
+ dependencies:
+ '@cowprotocol/sdk-common': 0.4.0
+ ethers: 6.14.3
+
'@cowprotocol/sdk-order-book@0.4.4':
dependencies:
'@cowprotocol/sdk-common': 0.4.0
diff --git a/scripts/generateColors/index.js b/scripts/generateColors/index.js
index 1363c700..62d28e59 100644
--- a/scripts/generateColors/index.js
+++ b/scripts/generateColors/index.js
@@ -34,7 +34,7 @@ const getColors = () => {
colors[theme][formattedTitle] = {
hex: value,
rgb: hexToRgb(value),
- isGradientColor: /-(start|end)$/.test(formattedTitle),
+ isGradientColor: /-(start|end)$/.test(formattedTitle)
}
}
})
@@ -98,7 +98,7 @@ const generateColors = () => {
newBaseFile = newBaseFile
.replace(
new RegExp(`:root .body-${theme}-theme {[^}]*}\n`, 'g'),
- `:root .body-${theme}-theme {\n${colorsBase[theme]} }\n`
+ `:root .body-${theme}-theme {\n${colorsBase[theme]} }\n`,
)
})
diff --git a/src/components/Dropdown/DropdownView/DropdownView.tsx b/src/components/Dropdown/DropdownView/DropdownView.tsx
index ef49a64e..6e7ea808 100644
--- a/src/components/Dropdown/DropdownView/DropdownView.tsx
+++ b/src/components/Dropdown/DropdownView/DropdownView.tsx
@@ -1,15 +1,14 @@
-import React, { Fragment, KeyboardEventHandler, ReactElement, ReactNode, useRef } from 'react'
+import React, { KeyboardEventHandler, ReactElement, ReactNode, useRef } from 'react'
import cx from 'classnames'
-import { offset, shift, VirtualElement, OffsetOptions } from '@floating-ui/react'
import type { Placement } from '@floating-ui/react'
import { autoUpdate, flip, useFloating } from '@floating-ui/react-dom'
+import { offset, shift, OffsetOptions } from '@floating-ui/react'
import { Listbox, ListboxButton, ListboxOptions, ListboxOption } from '@headlessui/react'
import s from './Dropdown.module.scss'
type ButtonInput = {
- ref: (node: Element | VirtualElement | null) => void
isOpen: boolean
}
@@ -18,8 +17,6 @@ export type DropdownViewProps = {
contentClassName?: string
children: ReactNode
disabled?: boolean
- // The child component must inherit the props, so be sure to make
- button: ReactElement | ((props: ButtonInput) => ReactElement)
value?: string
placement?: Placement
withArrow?: boolean
@@ -30,6 +27,7 @@ export type DropdownViewProps = {
autoUpdate?: boolean
offsetOptions?: Omit
}
+ button: (props: ButtonInput) => ReactElement
onOpen?: () => void
onClose?: () => void
onChange?: (value: any) => void
@@ -43,7 +41,7 @@ type DropdownViewComponent = React.FC & {
const DropdownView: DropdownViewComponent = (props: DropdownViewProps) => {
const {
- className, contentClassName, children, button, value, disabled, withArrow, middleware,
+ className, contentClassName, children, button, value, disabled, middleware,
placement = 'bottom-end', dataTestId, onOpen, onClose, onChange, onOptionsClick, onOptionsKeyDown,
} = props
@@ -72,11 +70,9 @@ const DropdownView: DropdownViewComponent = (props: DropdownViewProps) => {
value={value}
onChange={onChange}
>
-
+
{
({ open }) => {
- const arrow = open ? 'up' : 'down'
-
if (open && !isOpenRef.current && typeof onOpen === 'function') {
onOpen()
}
@@ -87,17 +83,8 @@ const DropdownView: DropdownViewComponent = (props: DropdownViewProps) => {
isOpenRef.current = open
- if (typeof button === 'function') {
- return button({
- ref: refs.setReference,
- isOpen: open,
- })
- }
-
- return React.cloneElement(button as any, {
- // @ts-ignore
- ref: refs.setReference,
- arrow: withArrow ? arrow : undefined,
+ return button({
+ isOpen: open,
})
}
}
diff --git a/src/components/Image/util/images.ts b/src/components/Image/util/images.ts
index b8257dcc..99d2a9b1 100644
--- a/src/components/Image/util/images.ts
+++ b/src/components/Image/util/images.ts
@@ -31,6 +31,7 @@ export const logos = [
'token/lsETH',
'token/stETH',
'token/wbETH',
+ 'token/wxDAI',
'token/wstETH',
'token/frxETH',
diff --git a/src/components/ImagesProvider/images/index.ts b/src/components/ImagesProvider/images/index.ts
index 9f1daf07..a50c00fe 100644
--- a/src/components/ImagesProvider/images/index.ts
+++ b/src/components/ImagesProvider/images/index.ts
@@ -27,6 +27,7 @@ import ezETH from './token/swap/ezETH.svg'
import lsETH from './token/swap/lsETH.svg'
import stETH from './token/swap/stETH.svg'
import wbETH from './token/swap/wbETH.svg'
+import wxDAI from './token/swap/wxDAI.svg'
import wstETH from './token/swap/wstETH.svg'
import frxETH from './token/swap/frxETH.svg'
@@ -120,6 +121,7 @@ export default {
'token/lsETH': lsETH.src,
'token/stETH': stETH.src,
'token/wbETH': wbETH.src,
+ 'token/wxDAI': wxDAI.src,
'token/wstETH': wstETH.src,
'token/frxETH': frxETH.src,
diff --git a/src/components/ImagesProvider/images/token/swap/wxDAI.svg b/src/components/ImagesProvider/images/token/swap/wxDAI.svg
new file mode 100644
index 00000000..fb6a579e
--- /dev/null
+++ b/src/components/ImagesProvider/images/token/swap/wxDAI.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/components/Select/SelectView/SelectView.tsx b/src/components/Select/SelectView/SelectView.tsx
index 4425795e..408e8ddb 100644
--- a/src/components/Select/SelectView/SelectView.tsx
+++ b/src/components/Select/SelectView/SelectView.tsx
@@ -40,7 +40,7 @@ const SelectView: React.FC = (props) => {
value={value}
withArrow
dataTestId={dataTestId}
- button={label ? (
+ button={({ isOpen }) => label ? (
= (props) => {
isError={isError}
title={selectedOption?.title}
dataTestId={`${dataTestId}-button`}
+ icon={isOpen ? 'arrow/up' : 'arrow/down'}
{...htmlAttrs}
/>
) : (
@@ -58,6 +59,7 @@ const SelectView: React.FC = (props) => {
logo={selectedOption?.logo}
title={selectedOption?.title}
dataTestId={`${dataTestId}-button`}
+ icon={isOpen ? 'arrow/up' : 'arrow/down'}
{...htmlAttrs}
/>
)}
diff --git a/src/components/TokenDropdown/TokenDropdown.tsx b/src/components/TokenDropdown/TokenDropdown.tsx
index fdfef161..0d5b9de8 100644
--- a/src/components/TokenDropdown/TokenDropdown.tsx
+++ b/src/components/TokenDropdown/TokenDropdown.tsx
@@ -1,8 +1,9 @@
import React, { useCallback } from 'react'
-import device from 'modules/device'
+import cx from 'classnames'
+import { Network } from 'sdk'
import { useConfig } from 'config'
import forms from 'modules/forms'
-import { Network } from 'sdk'
+import device from 'modules/device'
import Icon from '../Icon/Icon'
import ButtonBase from '../ButtonBase/ButtonBase'
@@ -19,15 +20,21 @@ export type TokenDropdownProps = Omit void
}
const TokenDropdown: React.FC = (props) => {
- const { className, contentClassName, value, tokens, dataTestId, isDisabled, onChange, ...rest } = props
+ const {
+ className, contentClassName, value, tokens, dataTestId = '', isDisabled, isFetchingDisabled,
+ onChange, ...rest
+ } = props
+ const { chainId } = useConfig()
const { isMobile } = device.useData()
- const { isReadOnlyMode, chainId } = useConfig()
- const { isFetching, open } = useTokenDropdown()
+ const { isFetching, open } = useTokenDropdown({
+ isFetchingDisabled,
+ })
const field = forms.useField({
valueType: 'string',
@@ -48,7 +55,7 @@ const TokenDropdown: React.FC = (props) => {
)
@@ -58,7 +65,9 @@ const TokenDropdown: React.FC = (props) => {
return (
= (props) => {
}
: undefined
)}
- button={({ ref, isOpen }) => (
+ button={({ isOpen }) => (
{tokenBaseNode}
{
- const { address, chainId } = useConfig()
- const [ { fetchedKey, isOpen, isFetching }, setState ] = useObjectState({
- fetchedKey: '',
- isOpen: false,
- isFetching: true,
- })
-
- const fetchRates = useSwapTokenRates()
- const { refetchSwapTokenBalances } = useBalances()
-
- const dataKey = `${address}-${chainId}`
-
- const handleFetch = useCallback(async () => {
- if (isOpen) {
- setState({ isFetching: true })
+const useTokenDropdown = ({ isFetchingDisabled }: Input) => {
+ const [ isOpen, setOpen ] = useState(false)
- await Promise.all([
- refetchSwapTokenBalances(),
- fetchRates(),
- ])
-
- setState({ fetchedKey: dataKey, isFetching: false })
- }
- }, [ isOpen, dataKey, setState, fetchRates, refetchSwapTokenBalances ])
-
- useChainChanged(handleFetch)
-
- useAutoFetch({
- action: handleFetch,
- interval: 15 * 60 * 1000,
- skip: !isOpen,
+ const { isFetching } = swapHooks.useData({
+ skip: !isOpen || isFetchingDisabled,
})
- const open = useCallback((isOpen: boolean) => {
- setState({ isOpen })
- }, [])
-
return useMemo(() => ({
- isFetching: isFetching && fetchedKey !== dataKey,
- open,
+ isFetching,
+ open: setOpen,
}), [
- dataKey,
- fetchedKey,
isFetching,
- open,
+ setOpen,
])
}
diff --git a/src/components/Transactions/types.d.ts b/src/components/Transactions/types.d.ts
index 5a981964..1b4d9cd2 100644
--- a/src/components/Transactions/types.d.ts
+++ b/src/components/Transactions/types.d.ts
@@ -1,10 +1,8 @@
import { Transaction, TransactionStatus } from './util'
-export type SetTransaction = (id: string | number, status: TransactionStatus) => void
+export type SetTransaction = (id: string | number, status: TransactionStatus, next?: boolean) => void
export type StepData = Partial>
-export type SetNextTransactionsFailed = (id: string | number) => void
-
export type StepsData = StepData[]
diff --git a/src/components/Transactions/util/useLogic.ts b/src/components/Transactions/util/useLogic.ts
index 1094a36c..ee2d0600 100644
--- a/src/components/Transactions/util/useLogic.ts
+++ b/src/components/Transactions/util/useLogic.ts
@@ -1,6 +1,4 @@
import { useCallback, useMemo, useState } from 'react'
-import type { SetNextTransactionsFailed } from 'components'
-
import type { SetTransaction } from '../types'
@@ -29,38 +27,21 @@ export type ModifiedTransaction = Omit & {
const useLogic = (initialTransactions: Transaction[] = []) => {
const [ transactions, setTransactions ] = useState(initialTransactions)
- const setTransaction: SetTransaction = useCallback((id, status) => {
+ const setTransaction: SetTransaction = useCallback((id, status, updateNextTransactions) => {
setTransactions((steps) => {
- return steps.map((step) => {
- if (step.id === id) {
- return {
- ...step,
- status,
- }
- }
+ const currentIndex = steps.findIndex((step) => step.id === id)
- return step
- })
- })
- }, [])
-
- const resetTransactions = useCallback(() => {
- setTransactions(initialTransactions)
- }, [ initialTransactions ])
-
- const setNextTransactionsFailed: SetNextTransactionsFailed = useCallback((id) => {
- setTransactions((steps) => {
- const failedIndex = steps.findIndex((step) => step.id === id)
-
- if (failedIndex === -1) {
+ if (currentIndex === -1) {
return steps
}
return steps.map((step, index) => {
- if (index >= failedIndex) {
+ const isStepToUpdate = updateNextTransactions ? index >= currentIndex : index === currentIndex
+
+ if (isStepToUpdate) {
return {
...step,
- status: TransactionStatus.Fail,
+ status,
}
}
@@ -69,6 +50,10 @@ const useLogic = (initialTransactions: Transaction[] = []) => {
})
}, [])
+ const resetTransactions = useCallback(() => {
+ setTransactions(initialTransactions)
+ }, [ initialTransactions ])
+
return useMemo(() => ({
transactions: transactions.map(({ onCancel, ...transaction }) => ({
...transaction,
@@ -79,13 +64,11 @@ const useLogic = (initialTransactions: Transaction[] = []) => {
setTransaction,
setTransactions,
resetTransactions,
- setNextTransactionsFailed,
}), [
transactions,
setTransaction,
setTransactions,
resetTransactions,
- setNextTransactionsFailed,
])
}
diff --git a/src/components/index.ts b/src/components/index.ts
index 3ce3c458..aac09c9d 100644
--- a/src/components/index.ts
+++ b/src/components/index.ts
@@ -137,7 +137,7 @@ export { default as Tooltip } from './Tooltip/Tooltip'
export type { TooltipProps } from './Tooltip/Tooltip'
export { default as Transactions } from './Transactions/Transactions'
-export type { SetTransaction, SetNextTransactionsFailed, StepsData } from './Transactions/types'
+export type { SetTransaction, StepsData } from './Transactions/types'
export { TransactionStatus } from './Transactions/util'
export type { Transaction } from './Transactions/util'
export type { TransactionsProps } from './Transactions/Transactions'
diff --git a/src/config/core/config/createConfig.tsx b/src/config/core/config/createConfig.tsx
index 5f23a37e..944d2389 100644
--- a/src/config/core/config/createConfig.tsx
+++ b/src/config/core/config/createConfig.tsx
@@ -17,6 +17,7 @@ const createConfig = (middleware?: ConfigProvider.Middleware) =
serverNetworkId,
supportedNetworkIds,
onFinishConnect,
+ onChangeAddress,
onStartConnect,
onConnectError,
onChangeChain,
@@ -28,6 +29,7 @@ const createConfig = (middleware?: ConfigProvider.Middleware) =
supportedNetworkIds,
serverNetworkId,
onFinishConnect,
+ onChangeAddress,
onStartConnect,
onConnectError,
onChangeChain,
diff --git a/src/config/core/config/types.d.ts b/src/config/core/config/types.d.ts
index b232d5d7..13a7e575 100644
--- a/src/config/core/config/types.d.ts
+++ b/src/config/core/config/types.d.ts
@@ -39,12 +39,6 @@ declare global {
unsubscribeBeforeChange: Subscription
}
- type CancelOnChangeInput = {
- logic: () => any
- chainId: ChainIds
- address: string | null
- }
-
type Context = T & State & {
wallet: Wallet
chainId: ChainIds
@@ -54,6 +48,7 @@ declare global {
type Callbacks = {
onStartConnect: (activationMessage: Intl.Message | string) => void
+ onChangeAddress?: () => void
onFinishConnect: () => void
onConnectError: () => void
onChangeChain?: () => void
diff --git a/src/config/core/config/util/getSpecialErrors.ts b/src/config/core/config/util/getSpecialErrors.ts
index 67ecd270..a0e9b9dc 100644
--- a/src/config/core/config/util/getSpecialErrors.ts
+++ b/src/config/core/config/util/getSpecialErrors.ts
@@ -35,18 +35,18 @@ const getSpecialErrors = (error: any) => {
return messages.connectErrors.ledger.settings
}
- if (error.name === 'TransportStatusError') {
- const statusCode = error.statusCode
- const isNotOpened = statusCode === 0x650f || statusCode === 0x6511
+ if (error.name === 'LockedDeviceError' && error.statusCode === 0x5515) {
+ return messages.connectErrors.ledger.lock
+ }
- return isNotOpened
- ? messages.connectErrors.ledger.notOpened
- : messages.connectErrors.ledger.lock
+ if (error.name === 'TransportStatusError' && [ 0x650f, 0x6511 ].includes(error.statusCode)) {
+ return messages.connectErrors.ledger.notOpened
}
const isNotConnected = (
- errorMessage.indexOf('0x6804') !== -1
- || errorMessage.indexOf('U2F DEVICE_INELIGIBLE') !== -1
+ errorMessage?.indexOf('0x6804') !== -1
+ || errorMessage?.indexOf('U2F DEVICE_INELIGIBLE') !== -1
+ || error.name === 'TransportOpenUserCancelled'
)
if (isNotConnected) {
diff --git a/src/config/core/config/util/useConfigContext.ts b/src/config/core/config/util/useConfigContext.ts
index 5b97bc55..4ddab4d6 100644
--- a/src/config/core/config/util/useConfigContext.ts
+++ b/src/config/core/config/util/useConfigContext.ts
@@ -24,6 +24,7 @@ const useConfigContext = (values: Input): ConfigProvider.Contex
serverNetworkId,
supportedNetworkIds,
onFinishConnect,
+ onChangeAddress,
onConnectError,
onStartConnect,
onChangeChain,
@@ -43,6 +44,15 @@ const useConfigContext = (values: Input): ConfigProvider.Contex
const setData = useCallback((data: Partial) => {
setState((state) => {
const isChainChanged = data.networkId && data.networkId !== state.networkId
+ const isAddressChanged = (
+ state.autoConnectChecked
+ && data.address !== state.address
+ && typeof data.address !== 'undefined'
+ )
+
+ if (isAddressChanged && typeof onChangeAddress === 'function') {
+ onChangeAddress()
+ }
if (isChainChanged && typeof onChangeChain === 'function') {
onChangeChain()
@@ -53,7 +63,7 @@ const useConfigContext = (values: Input): ConfigProvider.Contex
...data,
}
})
- }, [ onChangeChain, setState ])
+ }, [ onChangeChain, onChangeAddress, setState ])
const configState = useMemo(() => ({
data: state,
diff --git a/src/config/core/config/util/useStorageUpdate.ts b/src/config/core/config/util/useStorageUpdate.ts
index af3a4c95..af782bc3 100644
--- a/src/config/core/config/util/useStorageUpdate.ts
+++ b/src/config/core/config/util/useStorageUpdate.ts
@@ -3,8 +3,8 @@ import { localStorage } from 'sdk'
import cookie from 'helpers/cookie'
import * as constants from 'helpers/constants'
-import networks from './networks'
import wallets from '../../wallets'
+import networks from './networks'
const useStorageUpdate = (configState: ConfigProvider.ConfigState) => {
diff --git a/src/config/core/config/util/useWallet/useConnect.ts b/src/config/core/config/util/useWallet/useConnect.ts
index a1928948..3236335e 100644
--- a/src/config/core/config/util/useWallet/useConnect.ts
+++ b/src/config/core/config/util/useWallet/useConnect.ts
@@ -31,7 +31,6 @@ const useConnect = (values: Input) => {
const intlRef = intl.useIntlRef()
const inProgressRef = useRef(false)
const { dataRef, setData } = configState
- const timerRef = useRef(null)
const resetConnection = useCallback(() => {
notifications.open({
@@ -98,6 +97,11 @@ const useConnect = (values: Input) => {
resetConnectTimer = setTimeout(resetConnection, 10_000)
}
+ // In the safe app we need to resolve provider before next calls to avoid timeout error
+ if (isGnosisSafe && typeof connector.handleGetProvider === 'function') {
+ await connector.handleGetProvider()
+ }
+
if (activationMessage) {
onStartConnect(activationMessage)
}
@@ -172,10 +176,6 @@ const useConnect = (values: Input) => {
onFinishConnect()
- if (resetConnectTimer) {
- clearTimeout(resetConnectTimer)
- }
-
const networkId = networks.idByChain[chainId]
setData({
@@ -188,10 +188,6 @@ const useConnect = (values: Input) => {
})
inProgressRef.current = false
-
- if (timerRef.current) {
- clearTimeout(timerRef.current)
- }
}
catch (error: any) {
console.log(error)
@@ -206,10 +202,6 @@ const useConnect = (values: Input) => {
connector.deactivate?.()
- if (resetConnectTimer) {
- clearTimeout(resetConnectTimer)
- }
-
if (isWalletConnect) {
localStorage.clearAll()
}
@@ -238,6 +230,11 @@ const useConnect = (values: Input) => {
return Promise.reject(error)
}
+ finally {
+ if (resetConnectTimer) {
+ clearTimeout(resetConnectTimer)
+ }
+ }
}, [
intlRef,
dataRef,
diff --git a/src/config/core/config/util/useWallet/useDisconnect.ts b/src/config/core/config/util/useWallet/useDisconnect.ts
index b77dff0b..385ec1bd 100644
--- a/src/config/core/config/util/useWallet/useDisconnect.ts
+++ b/src/config/core/config/util/useWallet/useDisconnect.ts
@@ -1,5 +1,7 @@
import { useCallback } from 'react'
+import { localStorage } from 'sdk'
import intl from 'modules/intl'
+import * as constants from 'helpers/constants'
import notifications from 'modules/notifications'
import wallets from '../../../wallets'
@@ -39,6 +41,8 @@ const useDisconnect = (values: Input) => {
autoConnectChecked: true,
})
+ localStorage.removeItem(constants.localStorageNames.walletName)
+
if (activeWallet) {
const { title } = wallets[activeWallet]
const wallet = intlRef.current.formatMessage(title as Intl.MessageTranslation)
diff --git a/src/config/core/config/util/useWallet/useUpdateWallet.ts b/src/config/core/config/util/useWallet/useUpdateWallet.ts
index 70d4ce15..a74a96c8 100644
--- a/src/config/core/config/util/useWallet/useUpdateWallet.ts
+++ b/src/config/core/config/util/useWallet/useUpdateWallet.ts
@@ -1,7 +1,8 @@
import { useEffect, useCallback } from 'react'
import { getAddress, BrowserProvider } from 'ethers'
import type { Eip1193Provider } from 'ethers'
-import { methods } from 'helpers'
+import getSDK from 'helpers/methods/getSDK'
+import ens from 'helpers/methods/ens'
import networks from '../networks'
@@ -30,10 +31,10 @@ const useUpdateWallet = (values: Input) => {
const handleENS = useCallback(async () => {
const hasAccountName = Boolean(dataRef.current.accountName)
- const sdk = methods.getSDK({ chainId })
+ const sdk = getSDK({ chainId })
if (address) {
- methods.ens.fetchName({
+ ens.fetchName({
address,
chainId,
provider: sdk.provider,
diff --git a/src/config/core/connectors/BinanceConnector.ts b/src/config/core/connectors/BinanceConnector.ts
index f228fb7a..bb3a970a 100644
--- a/src/config/core/connectors/BinanceConnector.ts
+++ b/src/config/core/connectors/BinanceConnector.ts
@@ -1,8 +1,8 @@
'use client'
import { getProvider } from '@binance/w3w-ethereum-provider'
import EventAggregator from 'modules/event-aggregator'
-import apiUrls from 'helpers/methods/apiUrls'
import { AbstractProvider } from 'ethers'
+import apiUrls from 'helpers/methods/apiUrls'
import { Network } from 'sdk'
import networks from '../config/util/networks'
diff --git a/src/config/core/connectors/LedgerConnector/LedgerProvider.ts b/src/config/core/connectors/LedgerConnector/LedgerProvider.ts
index 30f84753..6a3de65f 100644
--- a/src/config/core/connectors/LedgerConnector/LedgerProvider.ts
+++ b/src/config/core/connectors/LedgerConnector/LedgerProvider.ts
@@ -1,6 +1,6 @@
import { configs, Network } from 'sdk'
import AppEth from '@ledgerhq/hw-app-eth'
-import * as methods from 'helpers/methods'
+import prefix0x from 'helpers/methods/prefix0x'
import { EIP712Message } from '@ledgerhq/types-live'
import { Signature, Transaction, isAddress, TypedDataEncoder } from 'ethers'
import type { TransactionLike, Eip1193Provider } from 'ethers'
@@ -183,14 +183,14 @@ class LedgerProvider extends LedgerTransport implements Eip1193Provider {
const path = this.#getDerivationPath()
const unsignedTx = Transaction.from(transaction).unsignedSerialized
- const rawTxHex = methods.prefix0x.remove(unsignedTx)
+ const rawTxHex = prefix0x.remove(unsignedTx)
const address = await app.getAddress(path)
const { r, s, v } = await app.signTransaction(path, rawTxHex)
const signature = {
- r: methods.prefix0x.add(r),
- s: methods.prefix0x.add(s),
+ r: prefix0x.add(r),
+ s: prefix0x.add(s),
v: parseInt(v),
// There is no "from" field in the signature parameters, but if you add it,
@@ -215,7 +215,7 @@ class LedgerProvider extends LedgerTransport implements Eip1193Provider {
async signPersonalMessage(data: string) {
return this.connectLedger(async (app: AppEth) => {
const path = this.#getDerivationPath()
- const formattedData = methods.prefix0x.remove(data)
+ const formattedData = prefix0x.remove(data)
const result = await app.signPersonalMessage(path, formattedData)
diff --git a/src/config/core/connectors/SafeAppConnector.ts b/src/config/core/connectors/SafeAppConnector.ts
index ca8d8946..8a6bfe76 100644
--- a/src/config/core/connectors/SafeAppConnector.ts
+++ b/src/config/core/connectors/SafeAppConnector.ts
@@ -30,8 +30,27 @@ class SafeAppConnector extends WagmiConnector {
})
}
+ async handleGetProvider(count: number = 0): Promise {
+ try {
+ const provider = await this.connector.getProvider()
+
+ return provider as SafeAppProvider
+ }
+ catch (error: any) {
+ const nextCount = count + 1
+
+ if (nextCount < 10) {
+ await new Promise((resolve) => setTimeout(resolve, nextCount * 100))
+
+ return this.handleGetProvider(nextCount)
+ }
+
+ return Promise.reject(error)
+ }
+ }
+
async getProvider() {
- const provider = await this.connector.getProvider() as SafeAppProvider
+ const provider = await this.handleGetProvider() as SafeAppProvider
const method = provider.request
@@ -63,7 +82,7 @@ class SafeAppConnector extends WagmiConnector {
}
}
catch {
- // getBySafeTxHash can catch error if hash if real and not a safeTxHash
+ // getBySafeTxHash can catch error if hash is real and not a safeTxHash
return response
}
}
@@ -81,7 +100,7 @@ class SafeAppConnector extends WagmiConnector {
}
try {
- const provider = await this.connector.getProvider()
+ const provider = await this.handleGetProvider()
return Boolean(provider)
}
diff --git a/src/config/core/global.d.ts b/src/config/core/global.d.ts
index cfbabacd..301fe69c 100644
--- a/src/config/core/global.d.ts
+++ b/src/config/core/global.d.ts
@@ -6,6 +6,7 @@ const walletsIds = Object.values(wallets).map(({ id }) => id)
declare global {
type WalletIds = typeof walletsIds[number]
+ type ReadOnlyConnector = ReadOnlyConnectorType
type NetworkIds = OneOfArray
type Connectors = Unpromise>
diff --git a/src/helpers/contracts/addresses.ts b/src/helpers/contracts/addresses.ts
index f642d2f6..56123ff2 100644
--- a/src/helpers/contracts/addresses.ts
+++ b/src/helpers/contracts/addresses.ts
@@ -9,6 +9,7 @@ const addresses = {
},
cow: {
vaultRelayer: '0xc92e8bdf79f0507f65a392b0ab4667716bfe0110',
+ nativeToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
},
},
[Network.Hoodi]: {
@@ -17,6 +18,7 @@ const addresses = {
},
cow: {
vaultRelayer: ZeroAddress,
+ nativeToken: ZeroAddress,
},
},
[Network.Gnosis]: {
@@ -25,6 +27,7 @@ const addresses = {
},
cow: {
vaultRelayer: '0xc92e8bdf79f0507f65a392b0ab4667716bfe0110',
+ nativeToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE',
},
},
}
diff --git a/src/helpers/cookie.ts b/src/helpers/cookie.ts
index 76e41470..fad42f8b 100644
--- a/src/helpers/cookie.ts
+++ b/src/helpers/cookie.ts
@@ -1,14 +1,15 @@
-import cookie, { CookieAttributes } from 'js-cookie'
+import cookie from 'js-cookie'
+import type Cookies from 'js-cookie'
import cookieNames from './constants/cookieNames'
const get = cookie.get
-const set = async (name: string, value: string, attributes: CookieAttributes = {}) => {
+const set = async (name: string, value: string, attributes: Cookies.CookieAttributes = {}) => {
const isValid = Object.values(cookieNames).includes(name)
- const options: CookieAttributes = attributes
+ const options: Cookies.CookieAttributes = attributes
if (!isValid) {
throw new Error(`Add cookie name "${name}" to constants`)
diff --git a/src/helpers/messages/index.ts b/src/helpers/messages/index.ts
index 10775d1a..e050af84 100644
--- a/src/helpers/messages/index.ts
+++ b/src/helpers/messages/index.ts
@@ -19,6 +19,15 @@ export default {
transaction,
notification,
accessibility,
+ exitDuration: {
+ en: 'Exit duration',
+ ru: 'Продолжительность выхода',
+ fr: 'Durée de sortie',
+ es: 'Duración de salida',
+ pt: 'Duração de saída',
+ de: 'Austrittsdauer',
+ zh: '退出持续时间',
+ },
upgradeLeverageStrategy: {
en: 'Upgrade leverage strategy contract',
ru: 'Обновить контракт стратегии с плечом',
diff --git a/src/helpers/messages/tooltip.ts b/src/helpers/messages/tooltip.ts
index 2373263c..f690550a 100644
--- a/src/helpers/messages/tooltip.ts
+++ b/src/helpers/messages/tooltip.ts
@@ -1,32 +1,12 @@
export default {
queue: {
- en: `
- The amount of {token} that enters the exit queue.
- It may take up to {queueDays} day(s) for the exit request to process.
- `,
- ru: `
- Количество {token}, которое входит в очередь выхода.
- Обработка запроса на выход может занять до {queueDays} дней.
- `,
- fr: `
- La quantité de {token} qui entre dans la file d'attente de sortie.
- Le traitement de la demande de sortie peut prendre jusqu'à {queueDays} jour(s).
- `,
- es: `
- La cantidad de {token} que ingresa a la cola de salida.
- Puede tomar hasta {queueDays} día(s) procesar la solicitud de salida.
- `,
- pt: `
- A quantidade de {token} que entra na fila de saída.
- Pode levar até {queueDays} dia(s) para processar a solicitação de saída.
- `,
- de: `
- Die Menge an {token}, die in die Austrittswarteschlange gelangt.
- Es kann bis zu {queueDays} Tag(e) dauern, bis die Austrittsanfrage bearbeitet wird.
- `,
- zh: `
- {token} 进入退出队列的数量。退出请求处理可能需要长达 {queueDays} 天。
- `,
+ en: 'The amount of {token} that enters the exit queue.',
+ ru: 'Количество {token}, которое попадает в очередь выхода.',
+ fr: 'Le montant de {token} qui entre dans la file de sortie.',
+ es: 'La cantidad de {token} que entra en la cola de salida.',
+ pt: 'A quantidade de {token} que entra na fila de saída.',
+ de: 'Der Betrag von {token}, der in die Ausstiegswarteschlange gelangt.',
+ zh: '{token} 进入退出队列的数量。',
},
gas: {
en: 'The fee (in {nativeToken}) you need to pay for the transaction to be confirmed by the network.',
@@ -155,4 +135,22 @@ export default {
目前,验证器退出并让 {depositToken} 可申领需要最多 {queueDays} 天。
`,
},
+ duration: {
+ en: 'It may take up to {queueDays, plural, one {# day} other {# days}} for an exit request to be processed on the {network} network.',
+ ru: 'Обработка запроса на выход в сети {network} может занять до {queueDays, plural, one {# дня} other {# дней}}.',
+ fr: 'Il peut falloir jusqu\'à {queueDays, plural, one {# jour} other {# jours}} pour qu\'une demande de sortie soit traitée sur le réseau {network}.',
+ es: 'Puede tardar hasta {queueDays, plural, one {# día} other {# días}} en procesarse una solicitud de salida en la red {network}.',
+ pt: 'Pode levar até {queueDays, plural, one {# dia} other {# dias}} para que um pedido de saída seja processado na rede {network}.',
+ de: 'Es kann bis zu {queueDays, plural, one {# Tag} other {# Tagen}} dauern, bis eine Ausstiegsanfrage im Netzwerk {network} bearbeitet wird.',
+ zh: '{network}网络上的退出请求可能需要最多{queueDays, plural, one {# 天} other {# 天}}来处理。',
+ },
+ avgDuration: {
+ en: 'On average, exits over the past month took {avgQueueDays, plural, one {# day} other {# days}} to complete',
+ ru: 'В среднем, выходы за прошлый месяц занимали {avgQueueDays, plural, one {# день} few {# дня} other {# дней}} для завершения',
+ fr: 'En moyenne, les sorties du mois dernier ont pris {avgQueueDays, plural, one {# jour} other {# jours}} pour se compléter',
+ es: 'En promedio, las salidas del último mes tomaron {avgQueueDays, plural, one {# día} other {# días}} en completarse',
+ pt: 'Em média, as saídas do último mês levaram {avgQueueDays, plural, one {# dia} other {# dias}} para serem concluídas',
+ de: 'Im Durchschnitt dauerten die Ausstiege im letzten Monat {avgQueueDays, plural, one {# Tag} other {# Tage}}',
+ zh: '平均而言,上个月完成退出耗时 {avgQueueDays, plural, one {# 天} other {# 天}}',
+ },
}
diff --git a/src/helpers/methods/formatFiatValue.ts b/src/helpers/methods/formatFiatValue.ts
index 0e99e27a..1cce2eca 100644
--- a/src/helpers/methods/formatFiatValue.ts
+++ b/src/helpers/methods/formatFiatValue.ts
@@ -14,7 +14,7 @@ const formatFiatValue = ({ value, currencySymbol, isMinimal }: Input) => {
formattedResult = `< ${currencySymbol} 0.01`
}
else {
- formattedResult = `${currencySymbol} ${formattedResult}`
+ formattedResult = `${currencySymbol}${formattedResult}`
}
return formattedResult
diff --git a/src/helpers/modifiers/formatDateToNumerical.ts b/src/helpers/modifiers/formatDateToNumerical.ts
index bac994b2..1aeeffb0 100644
--- a/src/helpers/modifiers/formatDateToNumerical.ts
+++ b/src/helpers/modifiers/formatDateToNumerical.ts
@@ -1,7 +1,7 @@
import date from 'modules/date'
-const formatDateToNumerical = (value: string | number | Date | ReturnType, separator: string = '-') => {
+const formatDateToNumerical = (value: string | number | Date | Date.Time, separator: string = '-') => {
let dayjsDate
if (typeof value === 'string') {
diff --git a/src/helpers/requests/vault/fetchData.ts b/src/helpers/requests/vault/fetchData.ts
index af909997..3de59453 100644
--- a/src/helpers/requests/vault/fetchData.ts
+++ b/src/helpers/requests/vault/fetchData.ts
@@ -1,6 +1,7 @@
import { Network } from 'sdk'
import * as methods from '../../methods'
+import fetchQueueDays from './fetchQueueDays'
type Input = {
@@ -22,10 +23,12 @@ const fetchData = async ({ sdk, withTime, vaultAddress }: Input) => {
data,
versions,
feePercent,
+ avgQueueDays,
] = await Promise.all([
sdk.vault.getVault({ vaultAddress, withTime }),
sdk.vault.getVaultVersion({ vaultAddress }),
sdk.contracts.base.mintTokenController.feePercent(),
+ fetchQueueDays({ sdk, vaultAddress }),
])
const chainId = sdk.config.network.chainId
@@ -41,6 +44,7 @@ const fetchData = async ({ sdk, withTime, vaultAddress }: Input) => {
...data,
versions,
isPostPectra,
+ avgQueueDays,
protocolFeePercent: String(feePercent / 100n),
}
}
diff --git a/src/helpers/requests/vault/fetchQueueDays.ts b/src/helpers/requests/vault/fetchQueueDays.ts
new file mode 100644
index 00000000..0ca1a892
--- /dev/null
+++ b/src/helpers/requests/vault/fetchQueueDays.ts
@@ -0,0 +1,49 @@
+import { methods } from 'helpers'
+
+
+type AvgExitQueueQueryPayload = {
+ vaults: Array<{
+ avgExitQueueLength: number
+ }>
+}
+type Input = {
+ sdk: SDK
+ vaultAddress: string
+}
+
+const fetchQueueDays = async (values: Input) => {
+ const { sdk, vaultAddress } = values
+
+ try {
+ const result = await methods.fetch(sdk.config.api.backend, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ query: `
+ query AvgExitQueue($vaultAddress: String!) {
+ vaults(id: $vaultAddress) {
+ avgExitQueueLength
+ }
+ }
+ `,
+ variables: {
+ vaultAddress,
+ },
+ }),
+ })
+
+ const seconds = result.vaults?.[0]?.avgExitQueueLength || 0
+
+ return Math.round(seconds / 86400)
+ }
+ catch (error: any) {
+ console.error('fetchQueueDays', error)
+
+ return 0
+ }
+}
+
+
+export default fetchQueueDays
diff --git a/src/helpers/swapTokens.ts b/src/helpers/swapTokens.ts
index 1f935db4..2c396c41 100644
--- a/src/helpers/swapTokens.ts
+++ b/src/helpers/swapTokens.ts
@@ -1,8 +1,10 @@
-import { Network } from 'sdk'
+import { Network, configs } from 'sdk'
const swapTokens = {
[Network.Mainnet]: {
+ osETH: configs[Network.Mainnet].addresses.tokens.mintToken,
+ SWISE: configs[Network.Mainnet].addresses.tokens.swise,
stETH: '0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84',
wbETH: '0xa2E3356610840701BDf5611a53974510Ae27E2e1',
rETH: '0xae78736Cd615f374D3085123A210448E74Fc6393',
@@ -24,17 +26,26 @@ const swapTokens = {
cmETH: '0xE6829d9a7eE3040e1276Fa75293Bde931859e8fA',
},
[Network.Gnosis]: {
+ osGNO: configs[Network.Gnosis].addresses.tokens.mintToken,
+ SWISE: configs[Network.Gnosis].addresses.tokens.swise,
wBTC: '0x8e5bBbb09Ed1ebdE8674Cda39A0c169401db4252',
USDT: '0x4ECaBa5870353805a9F068101A40E0f32ed605C6',
'USDC.e': '0x2a22f9c3b484c3629090FeED35F17Ff8F88f76F0',
EURe: '0xcB444e90D8198415266c6a2724b7900fb12FC56E',
sDAI: '0xaf204776c7245bF4147c2612BF6e5972Ee483701',
wstETH: '0x6C76971f98945AE98dD7d4DFcA8711ebea946eA6',
+ wxDAI: '0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d',
WETH: '0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1',
},
+ [Network.Hoodi]: {
+ osETH: configs[Network.Hoodi].addresses.tokens.mintToken,
+ },
}
const swapTokenTitles = {
+ osETH: 'StakeWise Staked ETH',
+ osGNO: 'StakeWise Staked GNO',
+ SWISE: 'StakeWise',
USDT: 'Tether USD',
USDC: 'USD Coin',
'USDC.e': 'USD Coin',
@@ -57,10 +68,19 @@ const swapTokenTitles = {
cmETH: 'Mantle Restaked ETH',
sDAI: 'Savings xDAI',
EURe: 'Monerium EUR emoney',
+ wxDAI: 'Wrapped xDAI',
+}
+
+const swapTokenCustomUnits = {
+ USDT: 6,
+ USDC: 6,
+ 'USDC.e': 6,
+ wBTC: 8,
}
export {
swapTokens,
swapTokenTitles,
+ swapTokenCustomUnits,
}
diff --git a/src/hooks/controls/useEventListener.ts b/src/hooks/controls/useEventListener.ts
index 256d7091..6008a8f6 100644
--- a/src/hooks/controls/useEventListener.ts
+++ b/src/hooks/controls/useEventListener.ts
@@ -5,7 +5,7 @@ import { useEffect, useRef, useCallback, RefObject } from 'react'
const useEventListener = (
eventName: string,
handler: EventListener,
- elementRef?: RefObject,
+ elementRef?: RefObject,
passive?: boolean
) => {
const handlerRef = useRef(null)
diff --git a/src/hooks/controls/useFieldListener.ts b/src/hooks/controls/useFieldListener.ts
index 301a625b..371edab0 100644
--- a/src/hooks/controls/useFieldListener.ts
+++ b/src/hooks/controls/useFieldListener.ts
@@ -1,6 +1,6 @@
'use client'
import { useEffect } from 'react'
-import { methods } from 'helpers'
+import debounce from 'helpers/methods/debounce'
type Procedure = (...args: any[]) => void
@@ -14,7 +14,7 @@ const useFieldListener = (
useEffect(() => {
if (typeof handler === 'function') {
const handleChangeField = wait
- ? methods.debounce(handler, wait)
+ ? debounce(handler, wait)
: handler
field.subscribe('change', handleChangeField)
diff --git a/src/hooks/controls/useImagesPrefetch.ts b/src/hooks/controls/useImagesPrefetch.ts
index 48643aab..082fb2be 100644
--- a/src/hooks/controls/useImagesPrefetch.ts
+++ b/src/hooks/controls/useImagesPrefetch.ts
@@ -1,19 +1,14 @@
'use client'
import { useEffect } from 'react'
-import cacheStorage from 'modules/cache-storage'
-
-const cache = cacheStorage.get('PREFETCHED_IMAGES')
-
-const useImagesPrefetch = (images: Record) => {
+const useImagesPrefetch = (images: Record, rel: 'prefetch' | 'preload' = 'prefetch') => {
useEffect(() => {
if (!images || !Object.values(images).length) {
return
}
- const cacheResult = cache.getData() || []
- const newImages = Object.values(images).filter((image) => !cacheResult.includes(image))
+ const newImages = Object.values(images)
if (!newImages.length) {
return
@@ -22,17 +17,13 @@ const useImagesPrefetch = (images: Record) => {
newImages.forEach((url) => {
const link = document.createElement('link')
- link.rel = 'prefetch'
+ link.rel = rel
link.as = 'image'
link.href = url
document.head.appendChild(link)
})
-
- const uniqueArrayOfImages = [ ...cacheResult, ...newImages ]
-
- cache.setData(uniqueArrayOfImages, 0)
- }, [ images ])
+ }, [ images, rel ])
}
diff --git a/src/hooks/controls/useModalClose.ts b/src/hooks/controls/useModalClose.ts
index 44b3a8e5..5e396bd8 100644
--- a/src/hooks/controls/useModalClose.ts
+++ b/src/hooks/controls/useModalClose.ts
@@ -1,5 +1,5 @@
-import { useEffect } from 'react'
-import { useConfig } from 'config'
+import useChainChanged from './useChainChanged'
+import useAddressChanged from './useAddressChanged'
type Input = {
@@ -9,16 +9,8 @@ type Input = {
const useModalClose = (values: Input) => {
const { closeModal } = values
- const { wallet } = useConfig()
-
- useEffect(() => {
- wallet.subscribeBeforeChange('chain', closeModal)
- wallet.subscribeBeforeChange('address', closeModal)
- return () => {
- wallet.unsubscribeBeforeChange('chain', closeModal)
- wallet.unsubscribeBeforeChange('address', closeModal)
- }
- }, [])
+ useChainChanged(closeModal)
+ useAddressChanged(closeModal)
}
diff --git a/src/hooks/controls/useTabButton.ts b/src/hooks/controls/useTabButton.ts
index e5ade1fb..e7d782a2 100644
--- a/src/hooks/controls/useTabButton.ts
+++ b/src/hooks/controls/useTabButton.ts
@@ -1,4 +1,4 @@
-import { useCallback, useLayoutEffect, useMemo, useRef } from 'react'
+import { useCallback, useEffect, useLayoutEffect, useMemo, useRef } from 'react'
import device from 'modules/device'
import intl from 'modules/intl'
@@ -6,10 +6,11 @@ import intl from 'modules/intl'
type Input = {
gap?: number
index: number
+ firstRenderClassName?: string
}
const useTabButton = (props: Input, deps: any[] = []) => {
- const { gap = 0, index = 0 } = props || {}
+ const { gap = 0, index = 0, firstRenderClassName } = props || {}
const { locale } = intl.useIntl()
const { isMobile } = device.useData()
@@ -20,16 +21,19 @@ const useTabButton = (props: Input, deps: any[] = []) => {
const getPosition = useCallback((index: number) => {
if (containerRef.current) {
const buttons = Array.from(containerRef.current.children) as HTMLButtonElement[]
- const widths = buttons.map(({ offsetWidth }) => offsetWidth)
- const height = buttons.map(({ offsetHeight }) => offsetHeight).reduce((acc, height) => Math.max(acc, height), 0)
+ const sizes = buttons.map((button) => button.getBoundingClientRect())
+ const widths = sizes.map(({ width }) => width)
+ const height = sizes.reduce((acc, { height }) => Math.max(acc, height), 0)
const offset = widths
.filter((_, widthIndex) => widthIndex < index)
- .reduce((acc, width) => acc + width + gap, 0)
+ .reduce((acc, width) => acc + width, 0)
+
+ const gapOffset = gap * index
if (widths[index] && height) {
return {
- left: `${offset}px`,
+ left: `calc(${offset}px + ${gapOffset}rem)`,
width: `${widths[index]}px`,
height: `${height}px`,
}
@@ -68,6 +72,20 @@ const useTabButton = (props: Input, deps: any[] = []) => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [ ...deps, locale, isMobile, setPosition ])
+ useEffect(() => {
+ const children = containerRef.current?.children
+
+ if (children && firstRenderClassName) {
+ Array.from(children).forEach((button) => {
+ if (button !== tabButtonRef.current) {
+ const classNames = firstRenderClassName.split(' ')
+
+ button.classList.remove(...classNames)
+ }
+ })
+ }
+ }, [ firstRenderClassName, ...deps ])
+
return useMemo(() => ({
tabButtonRef,
containerRef,
diff --git a/src/hooks/data/useClaimsTotal.ts b/src/hooks/data/useClaimsTotal.ts
index 62bd98c3..a4de4b41 100644
--- a/src/hooks/data/useClaimsTotal.ts
+++ b/src/hooks/data/useClaimsTotal.ts
@@ -1,7 +1,8 @@
import { useMemo } from 'react'
-import { methods } from 'helpers'
import { useConfig } from 'config'
import { formatEther } from 'ethers'
+import getFiatValue from 'helpers/methods/getFiatValue'
+import formatFiatValue from 'helpers/methods/formatFiatValue'
import useStore from './useStore'
@@ -25,7 +26,7 @@ const useClaimsTotal = () => {
const tokenKeys = Object.keys(sdk.config.addresses.tokens).reduce((acc, tokenKey) => {
const tokenAddress = sdk.config.addresses.tokens[tokenKey as keyof typeof sdk.config.addresses.tokens]
- acc[tokenAddress] = tokenKey
+ acc[tokenAddress.toLowerCase()] = tokenKey
return acc
}, {} as Record)
@@ -33,11 +34,11 @@ const useClaimsTotal = () => {
let amount = 0
tokens.forEach((tokenAddress, index) => {
- const tokenKey = tokenKeys[tokenAddress]
+ const tokenKey = tokenKeys[tokenAddress.toLowerCase()]
const tokenName = sdk.config.tokens[tokenKey as keyof typeof sdk.config.tokens]
const value = formatEther(unclaimedAmounts[index])
- const fiatValue = methods.getFiatValue({
+ const fiatValue = getFiatValue({
token: tokenName,
value,
currency,
@@ -48,7 +49,7 @@ const useClaimsTotal = () => {
})
if (amount) {
- return methods.formatFiatValue({
+ return formatFiatValue({
value: amount,
currencySymbol,
isMinimal: true,
diff --git a/src/hooks/data/useFiatValues.ts b/src/hooks/data/useFiatValues.ts
index 8aec3832..4bc8c3ea 100644
--- a/src/hooks/data/useFiatValues.ts
+++ b/src/hooks/data/useFiatValues.ts
@@ -1,12 +1,13 @@
-import { methods } from 'helpers'
import { useMemo, useCallback } from 'react'
-import { createSelector } from '@reduxjs/toolkit'
+import swGetFiatValue from 'helpers/methods/getFiatValue'
+import { useSelector, createSelector } from 'store'
+import formatFiatValue from 'helpers/methods/formatFiatValue'
-import useStore from '../data/useStore'
+type FiatToken = Extract
type Input = Record
@@ -36,7 +37,7 @@ const mock = {
}
const useFiatValues = (values: Input): Output => {
- const { fiatRates, swapTokenRates, currency, currencySymbol, isFetching } = useStore(storeSelector)
+ const { fiatRates, swapTokenRates, currency, currencySymbol, isFetching } = useSelector(storeSelector)
const getFiatValue = useCallback((params: Input[T]) => {
const { token, value, isMinimal } = params
@@ -45,7 +46,7 @@ const useFiatValues = (values: Input): Output => {
return mock
}
- const allRates = { ...fiatRates, ...swapTokenRates }
+ const allRates = { ...swapTokenRates, ...fiatRates }
const isValidToken = Object.keys(allRates).includes(token)
@@ -54,7 +55,7 @@ const useFiatValues = (values: Input): Output => {
return mock
}
- const fiatValue = methods.getFiatValue({
+ const fiatValue = swGetFiatValue({
value,
token,
currency,
@@ -62,7 +63,7 @@ const useFiatValues = (values: Input): Output => {
isMinimal,
})
- const formattedValue = methods.formatFiatValue({
+ const formattedValue = formatFiatValue({
value: fiatValue,
currencySymbol,
isMinimal,
diff --git a/src/hooks/data/useMintToken.ts b/src/hooks/data/useMintToken.ts
index 7ba31044..56b25fa4 100644
--- a/src/hooks/data/useMintToken.ts
+++ b/src/hooks/data/useMintToken.ts
@@ -1,16 +1,28 @@
'use client'
import { useCallback } from 'react'
+import insertMockE2E from 'helpers/methods/insertMockE2E'
type Input = {
sdk: SDK
}
+type Output = {
+ apy: string
+ feePercent: number
+}
+
const useMintToken = (values: Input) => {
const { sdk } = values
const fetchAPY = useCallback(async () => {
try {
+ const mockE2E = insertMockE2E