Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions e2e/fixtures/swap/helpers/checkTokenDropdown.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,22 @@ 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' })

await page.getByTestId('amount-input-token').click()

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()
}
)
1 change: 1 addition & 0 deletions e2e/fixtures/vault/setVaultData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export const createSetVaultData: Wrapper = ({ page }) => (
},
isPostPectra: true,
protocolFeePercent: String(feePercent / 100),
avgQueueDays: 1,
}

await page.addInitScript((payload) => {
Expand Down
2 changes: 1 addition & 1 deletion e2e/tests/stake.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 }) => {
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
13 changes: 13 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions scripts/generateColors/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const getColors = () => {
colors[theme][formattedTitle] = {
hex: value,
rgb: hexToRgb(value),
isGradientColor: /-(start|end)$/.test(formattedTitle),
isGradientColor: /-(start|end)$/.test(formattedTitle)
}
}
})
Expand Down Expand Up @@ -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`,
)
})

Expand Down
27 changes: 7 additions & 20 deletions src/components/Dropdown/DropdownView/DropdownView.tsx
Original file line number Diff line number Diff line change
@@ -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
}

Expand All @@ -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 <Foo {...props} />
button: ReactElement | ((props: ButtonInput) => ReactElement)
value?: string
placement?: Placement
withArrow?: boolean
Expand All @@ -30,6 +27,7 @@ export type DropdownViewProps = {
autoUpdate?: boolean
offsetOptions?: Omit<OffsetOptions, 'number'>
}
button: (props: ButtonInput) => ReactElement
onOpen?: () => void
onClose?: () => void
onChange?: (value: any) => void
Expand All @@ -43,7 +41,7 @@ type DropdownViewComponent = React.FC<DropdownViewProps> & {

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

Expand Down Expand Up @@ -72,11 +70,9 @@ const DropdownView: DropdownViewComponent = (props: DropdownViewProps) => {
value={value}
onChange={onChange}
>
<ListboxButton as={Fragment}>
<ListboxButton as="div" ref={refs.setReference}>
{
({ open }) => {
const arrow = open ? 'up' : 'down'

if (open && !isOpenRef.current && typeof onOpen === 'function') {
onOpen()
}
Expand All @@ -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<HTMLButtonElement>(button as any, {
// @ts-ignore
ref: refs.setReference,
arrow: withArrow ? arrow : undefined,
return button({
isOpen: open,
})
}
}
Expand Down
1 change: 1 addition & 0 deletions src/components/Image/util/images.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export const logos = [
'token/lsETH',
'token/stETH',
'token/wbETH',
'token/wxDAI',
'token/wstETH',
'token/frxETH',

Expand Down
2 changes: 2 additions & 0 deletions src/components/ImagesProvider/images/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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'

Expand Down Expand Up @@ -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,

Expand Down
1 change: 1 addition & 0 deletions src/components/ImagesProvider/images/token/swap/wxDAI.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 3 additions & 1 deletion src/components/Select/SelectView/SelectView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,15 @@ const SelectView: React.FC<SelectViewProps> = (props) => {
value={value}
withArrow
dataTestId={dataTestId}
button={label ? (
button={({ isOpen }) => label ? (
<SelectWithLabelButton
className="w-full"
label={label}
fullWidth
isError={isError}
title={selectedOption?.title}
dataTestId={`${dataTestId}-button`}
icon={isOpen ? 'arrow/up' : 'arrow/down'}
{...htmlAttrs}
/>
) : (
Expand All @@ -58,6 +59,7 @@ const SelectView: React.FC<SelectViewProps> = (props) => {
logo={selectedOption?.logo}
title={selectedOption?.title}
dataTestId={`${dataTestId}-button`}
icon={isOpen ? 'arrow/up' : 'arrow/down'}
{...htmlAttrs}
/>
)}
Expand Down
29 changes: 18 additions & 11 deletions src/components/TokenDropdown/TokenDropdown.tsx
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -19,15 +20,21 @@ export type TokenDropdownProps = Omit<DropdownViewProps, 'children' | 'button' |
value: Tokens
tokens: SwapToken[]
isDisabled?: boolean
isFetchingDisabled?: boolean
onChange?: (value: string) => void
}

const TokenDropdown: React.FC<TokenDropdownProps> = (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<string>({
valueType: 'string',
Expand All @@ -48,7 +55,7 @@ const TokenDropdown: React.FC<TokenDropdownProps> = (props) => {
<TokenBase
className="flex-shrink-0"
token={value}
dataTestId="amount-input-token"
dataTestId={`${dataTestId}-token`}
/>
)

Expand All @@ -58,7 +65,9 @@ const TokenDropdown: React.FC<TokenDropdownProps> = (props) => {

return (
<DropdownView
className={className}
className={cx(className, {
'opacity-50': isDisabled,
})}
contentClassName={contentClassName}
dataTestId={dataTestId}
middleware={(
Expand All @@ -73,12 +82,10 @@ const TokenDropdown: React.FC<TokenDropdownProps> = (props) => {
}
: undefined
)}
button={({ ref, isOpen }) => (
button={({ isOpen }) => (
<ButtonBase
// @ts-ignore
ref={ref}
className="flex items-center gap-8"
disabled={isReadOnlyMode || isDisabled}
disabled={isDisabled}
>
{tokenBaseNode}
<Icon
Expand Down
60 changes: 11 additions & 49 deletions src/components/TokenDropdown/util/useTokenDropdown.ts
Original file line number Diff line number Diff line change
@@ -1,62 +1,24 @@
import { useCallback, useMemo } from 'react'
import { useConfig } from 'config'
import { useBalances, useChainChanged, useAutoFetch, useObjectState } from 'hooks'
import { useMemo, useState } from 'react'
import { swapHooks } from 'hooks'

import useSwapTokenRates from './useSwapTokenRates'


type State = {
fetchedKey: string
isOpen: boolean
isFetching: boolean
type Input = {
isFetchingDisabled?: boolean
}

const useTokenDropdown = () => {
const { address, chainId } = useConfig()
const [ { fetchedKey, isOpen, isFetching }, setState ] = useObjectState<State>({
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,
])
}

Expand Down
4 changes: 1 addition & 3 deletions src/components/Transactions/types.d.ts
Original file line number Diff line number Diff line change
@@ -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<Pick<Transaction, 'id' | 'title' | 'onCancel'>>

export type SetNextTransactionsFailed = (id: string | number) => void

export type StepsData = StepData[]
Loading
Loading