Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(Trader): refetch data every 20 seconds #11852

Merged
merged 5 commits into from
Oct 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 4 additions & 1 deletion packages/plugins/Trader/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"dependencies": {
"@ethersproject/providers": "^5.7.2",
"@hookform/resolvers": "^3.6.0",
"@masknet/icons": "workspace:^",
"@masknet/plugin-infra": "workspace:^",
"@masknet/plugin-transak": "workspace:^",
Expand All @@ -36,11 +37,13 @@
"date-fns": "^2.30.0",
"fuse.js": "^7.0.0",
"immer": "^10.1.1",
"react-hook-form": "^7.53.0",
"react-router-dom": "^6.24.0",
"react-use": "^17.4.0",
"urlcat": "^3.1.0",
"use-subscription": "^1.8.0",
"web3-core": "1.10.4"
"web3-core": "1.10.4",
"zod": "^3.23.8"
},
"lingui": {
"catalogs": [
Expand Down
8 changes: 7 additions & 1 deletion packages/plugins/Trader/src/SiteAdaptor/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ export const enum RoutePaths {
export const DEFAULT_SLIPPAGE = '0.5'

export const QUOTE_STALE_DURATION = 20_000
export const REFETCH_INTERVAL = 20_000

export const bridges = [
{
Expand All @@ -33,7 +34,7 @@ export const bridges = [
{
id: 315,
name: 'Across',
logoUrl: new URL('../assets/accross.svg', import.meta.url).href,
logoUrl: new URL('../assets/across.svg', import.meta.url).href,
},
{
id: 211,
Expand Down Expand Up @@ -77,4 +78,9 @@ export const bridges = [
logoUrl:
'https://static.okx.com/cdn/explorer/dex/logo/dex_Circle.png.png?x-oss-process=image/format,webp/ignore-error,1',
},
{
id: 476,
name: 'Bungee Refuel',
logoUrl: 'https://www.okx.com/cdn/web3/dex/logo/b53506a1-fc2b-439d-9696-8eaea55167ca.png',
},
]
2 changes: 1 addition & 1 deletion packages/plugins/Trader/src/SiteAdaptor/trader/Routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { BridgeConfirm } from './views/BridgeConfirm.js'
import { BridgeQuoteRoute } from './views/BridgeQuoteRoute.js'
import { Confirm } from './views/Confirm.js'
import { HistoryView } from './views/History.js'
import { NetworkFee } from './views/NetworkFee.js'
import { NetworkFee } from './views/NetworkFee/index.js'
import { QuoteRoute } from './views/QuoteRoute.js'
import { SelectLiquidity } from './views/SelectLiquidity.js'
import { Slippage } from './views/Slippage.js'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { OKX } from '@masknet/web3-providers'
import type { GetBridgeQuoteOptions } from '@masknet/web3-providers/types'
import { useQuery } from '@tanstack/react-query'
import { QUOTE_STALE_DURATION } from '../../constants.js'
import { QUOTE_STALE_DURATION, REFETCH_INTERVAL } from '../../constants.js'

export function useBridgeQuotes(options: Partial<GetBridgeQuoteOptions>, enabled = true) {
const valid =
Expand All @@ -19,5 +19,6 @@ export function useBridgeQuotes(options: Partial<GetBridgeQuoteOptions>, enabled
queryKey: ['okx-bridge', 'get-quotes', options],
queryFn: () => OKX.getBridgeQuote(options as GetBridgeQuoteOptions),
staleTime: QUOTE_STALE_DURATION,
refetchInterval: REFETCH_INTERVAL,
})
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { OKX } from '@masknet/web3-providers'
import type { ChainId } from '@masknet/web3-shared-evm'
import { skipToken, useQuery } from '@tanstack/react-query'
import { REFETCH_INTERVAL } from '../../constants.js'

export function useLiquidityResources(chainId: ChainId, enabled = true) {
return useQuery({
Expand All @@ -13,5 +14,6 @@ export function useLiquidityResources(chainId: ChainId, enabled = true) {
return res?.code === 0 ? res.data : undefined
}
: skipToken,
refetchInterval: REFETCH_INTERVAL,
})
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { OKX } from '@masknet/web3-providers'
import type { GetQuotesOptions } from '@masknet/web3-providers/types'
import { useQuery } from '@tanstack/react-query'
import { QUOTE_STALE_DURATION } from '../../constants.js'
import { isGreaterThan } from '@masknet/web3-shared-base'
import { useQuery } from '@tanstack/react-query'
import { QUOTE_STALE_DURATION, REFETCH_INTERVAL } from '../../constants.js'

export function useQuotes(options: Partial<GetQuotesOptions>, enabled = true) {
const valid =
Expand All @@ -12,5 +12,6 @@ export function useQuotes(options: Partial<GetQuotesOptions>, enabled = true) {
queryKey: ['okx-swap', 'get-quotes', options],
queryFn: () => OKX.getQuotes(options as GetQuotesOptions),
staleTime: QUOTE_STALE_DURATION,
refetchInterval: REFETCH_INTERVAL,
})
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { zodResolver } from '@hookform/resolvers/zod'
import { t, Trans } from '@lingui/macro'
import { Icons } from '@masknet/icons'
import { ProgressiveText } from '@masknet/shared'
Expand All @@ -14,11 +15,16 @@ import {
} from '@masknet/web3-shared-evm'
import { Box, Button, Typography } from '@mui/material'
import { BigNumber } from 'bignumber.js'
import { isEmpty } from 'lodash-es'
import { memo, useMemo, useRef, useState } from 'react'
import { Controller, useForm } from 'react-hook-form'
import { useNavigate } from 'react-router-dom'
import { GasCost } from '../../components/GasCost.js'
import { Warning } from '../../components/Warning.js'
import { useGasManagement, useTrade } from '../contexts/index.js'
import { type z as zod } from 'zod'
import { GasCost } from '../../../components/GasCost.js'
import { Warning } from '../../../components/Warning.js'
import { useGasManagement } from '../../contexts/GasManager.js'
import { useTrade } from '../../contexts/TradeProvider.js'
import { useSchema } from './schema.js'

const useStyles = makeStyles<void, 'active' | 'gasWarning' | 'gasOk'>()((theme, _, refs) => ({
container: {
Expand Down Expand Up @@ -114,6 +120,11 @@ const useStyles = makeStyles<void, 'active' | 'gasWarning' | 'gasOk'>()((theme,
color: theme.palette.maskColor.second,
marginLeft: theme.spacing(1.5),
},
error: {
color: theme.palette.maskColor.danger,
fontSize: 13,
lineHeight: '18px',
},
}))

function formatTimeCost(seconds: number | undefined) {
Expand All @@ -124,8 +135,8 @@ function formatTimeCost(seconds: number | undefined) {
}

const MIN_BASE_FEE = '0.01'
const gweiToWei = (gwei: BigNumber.Value | undefined) => formatGweiToWei(gwei ?? '0').toFixed()
const weiToGwei = (wei: BigNumber.Value | undefined) => formatWeiToGwei(wei ?? '0').toFixed()
const gweiToWei = (gwei: BigNumber.Value | undefined) => (gwei ? formatGweiToWei(gwei).toFixed() : undefined)
const weiToGwei = (wei: BigNumber.Value | undefined) => (wei ? formatWeiToGwei(wei).toFixed() : undefined)
export const NetworkFee = memo(function NetworkFee() {
const { classes, cx, theme } = useStyles()
const { chainId } = useTrade()
Expand All @@ -152,9 +163,10 @@ export const NetworkFee = memo(function NetworkFee() {
const [priorityFee = defaultPriorityFee, setPriorityFee] = useState<string>()
const [gasPrice = defaultGasPrice, setGasPrice] = useState<string>()
const customFeePrice = useMemo(
() => (isSupport1559 ? plus(baseFee ?? '0', priorityFee ?? '0') : new BigNumber(gasPrice ?? '0')),
() => (isSupport1559 ? plus(baseFee || '0', priorityFee || '0') : new BigNumber(gasPrice ?? '0')),
[isSupport1559, baseFee, priorityFee, gasPrice],
)

const isTooHigh = isGreaterThan(customFeePrice, multipliedBy(gasOptions?.fast.suggestedMaxFeePerGas ?? '0', 2))

const customBoxRef = useRef<HTMLDivElement>(null)
Expand Down Expand Up @@ -192,6 +204,20 @@ export const NetworkFee = memo(function NetworkFee() {
}
}, [gasOptions, customFeePrice])

const schema = useSchema(isSupport1559)

const {
control,
setValue,
formState: { errors },
} = useForm<zod.infer<typeof schema>>({
mode: 'onChange',
resolver: zodResolver(schema),
context: {
gasOptions,
},
})

return (
<div className={classes.container}>
<div
Expand Down Expand Up @@ -324,7 +350,7 @@ export const NetworkFee = memo(function NetworkFee() {
<Trans>Custom</Trans>
</Typography>
<Typography className={classes.boxSubtitle} variant="h3">
{formatWeiToGwei(customFeePrice ?? '0').toFixed()} Gwei
{customFeePrice ? formatWeiToGwei(customFeePrice).toFixed() : '--'} Gwei
</Typography>
</div>
<div className={classes.boxTail}>
Expand All @@ -350,29 +376,72 @@ export const NetworkFee = memo(function NetworkFee() {
<Trans>Base fee required: {MIN_BASE_FEE} Gwei</Trans>
</Typography>
</Box>
<MaskTextField
placeholder="0.1-50"
type="number"
value={weiToGwei(baseFee)}
onChange={(e) => {
setBaseFee(gweiToWei(e.target.value))
}}
InputProps={{
endAdornment: <Typography className={classes.gwei}>Gwei</Typography>,
<Controller
control={control}
name="baseFee"
render={({ field, fieldState }) => {
return (
<>
<MaskTextField
{...field}
placeholder="0.1-50"
type="number"
value={weiToGwei(baseFee)}
onChange={(e) => {
const value = gweiToWei(e.target.value) || ''
setBaseFee(value)
setValue('baseFee', value)
field.onChange(e)
}}
InputProps={{
endAdornment: (
<Typography className={classes.gwei}>Gwei</Typography>
),
}}
/>
{fieldState.error ?
<Typography className={classes.error}>
{fieldState.error.message}
</Typography>
: null}
</>
)
}}
/>
<Typography className={classes.fieldName}>
<Trans>Priority fee</Trans>
</Typography>
<MaskTextField
placeholder="0.1-50"
type="number"
value={weiToGwei(priorityFee)}
onChange={(e) => {
setPriorityFee(gweiToWei(e.target.value))
}}
InputProps={{
endAdornment: <Typography className={classes.gwei}>Gwei</Typography>,

<Controller
control={control}
name="priorityFee"
render={({ field, fieldState }) => {
return (
<>
<MaskTextField
{...field}
placeholder="0.1-50"
type="number"
value={weiToGwei(priorityFee)}
onChange={(e) => {
const value = gweiToWei(e.target.value) || ''
setPriorityFee(value)
setValue('priorityFee', value)
field.onChange(e)
}}
InputProps={{
endAdornment: (
<Typography className={classes.gwei}>Gwei</Typography>
),
}}
/>
{fieldState.error ?
<Typography className={classes.error}>
{fieldState.error.message}
</Typography>
: null}
</>
)
}}
/>
</>
Expand All @@ -382,15 +451,36 @@ export const NetworkFee = memo(function NetworkFee() {
<Trans>Gas Price</Trans>
</Typography>
</Box>
<MaskTextField
placeholder="0.1-50"
type="number"
value={weiToGwei(gasPrice)}
onChange={(e) => {
setGasPrice(gweiToWei(e.target.value || '0'))
}}
InputProps={{
endAdornment: <Typography className={classes.gwei}>Gwei</Typography>,
<Controller
control={control}
name="gasPrice"
render={({ field, fieldState }) => {
return (
<>
<MaskTextField
{...field}
placeholder="0.1-50"
type="number"
value={weiToGwei(gasPrice)}
onChange={(e) => {
const value = gweiToWei(e.target.value) || ''
setGasPrice(value)
setValue('gasPrice', value)
field.onChange(e)
}}
InputProps={{
endAdornment: (
<Typography className={classes.gwei}>Gwei</Typography>
),
}}
/>
{fieldState.error ?
<Typography className={classes.error}>
{fieldState.error.message}
</Typography>
: null}
</>
)
}}
/>
</>
Expand All @@ -407,7 +497,7 @@ export const NetworkFee = memo(function NetworkFee() {
<Button
variant="roundedContained"
fullWidth
disabled={disabled}
disabled={disabled || !isEmpty(errors)}
onClick={() => {
if (isSupport1559) {
const maxFeePerGas = plus(baseFee ?? '0', priorityFee ?? '0').toFixed()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { t } from '@lingui/macro'
import { isGreaterThan, isLessThan } from '@masknet/web3-shared-base'
import { useMemo } from 'react'
import { z as zod } from 'zod'

const gtZero = (v: string) => isGreaterThan(v, 0)
export function useSchema(supported1559: boolean, minGasLimit = 21000) {
const gasLimit = zod
.string()
.min(1, t`Enter gas limit`)
.refine(
(gasLimit) => isGreaterThan(gasLimit, minGasLimit) && isLessThan(gasLimit, 150_000),
t`Gas limit should be between ${minGasLimit} and 15.00M`,
)
return useMemo(() => {
if (supported1559) {
return zod.object({
gasLimit,
priorityFee: zod.string().refine(gtZero, t`Max base fee should be greater than 0`),
baseFee: zod.string().refine(gtZero, t`Max base fee should be greater than 0`),
})
}
return zod.object({
gasLimit,
gasPrice: zod.string().refine(gtZero, t`Gas price should be greater than 0`),
})
}, [supported1559, minGasLimit])
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
} from '@masknet/web3-shared-base'
import { isNativeTokenAddress, type ChainId } from '@masknet/web3-shared-evm'
import { Box, Button, Typography } from '@mui/material'
import { BigNumber } from 'bignumber.js'
import { useMemo, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import urlcat from 'urlcat'
Expand Down Expand Up @@ -256,6 +257,7 @@ export function TradeView() {
)
if (picked) {
setInputAmount('')
setIsMax(false)
setFromToken(picked)
if (toChainId !== picked.chainId && isSwap) setToToken(undefined)
}
Expand Down Expand Up @@ -296,7 +298,9 @@ export function TradeView() {
if (!fromToken?.address) return
const isNative = isNativeTokenAddress(fromToken.address)
const balance =
isNative ? minus(fromTokenBalance, gasFee) : fromTokenBalance
isNative ?
BigNumber.max(minus(fromTokenBalance, gasFee), 0)
: fromTokenBalance
setInputAmount(trimZero(leftShift(balance, fromToken.decimals).toFixed()))
setIsMax(true)
}}>
Expand Down
Loading