Skip to content

Commit

Permalink
feat: gas setting (#10200)
Browse files Browse the repository at this point in the history
* feat: gas setting

* fix: bugfix

* fix: add rule

* feat: support replace transaction

* chore: code style
  • Loading branch information
nuanyang233 authored Jul 28, 2023
1 parent dafa792 commit 357f049
Show file tree
Hide file tree
Showing 13 changed files with 584 additions and 11 deletions.
16 changes: 13 additions & 3 deletions packages/mask/shared-ui/locales/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"operation": "Operation",
"gas_limit": "Gas Limit",
"gas_price": "Gas Price",
"gwei": "Gwei",
"redirect_to": "Redirect to",
"welcome_back": "Welcome Back",
"sign": "Sign",
Expand Down Expand Up @@ -247,7 +248,7 @@
"select_friends_dialog_persona_connect_other": "The Persona is connected to accounts",
"service_decryption_failed": "Decryption failed.",
"service_username_invalid": "Invalid Username",
"speed_up": "Speed up",
"speed_up": "Speed Up",
"save": "Save",
"skip": "Skip",
"next": "Next",
Expand Down Expand Up @@ -919,11 +920,20 @@
"popups_wallet_gas_fee_settings_low": "Low",
"popups_wallet_gas_fee_settings_medium": "Medium",
"popups_wallet_gas_fee_settings_high": "High",
"popups_wallet_gas_fee_settings_instant": "Instant",
"popups_wallet_gas_fee_settings_custom": "Custom",
"popups_wallet_gas_fee": "Gas Fee",
"popups_wallet_gas_price_too_low": "Gas Price too low will cause the transaction to fail.",
"popups_wallet_gas_price_estimate_second": "Likely in < {{seconds}} seconds",
"popups_wallet_gas_price_current_base_fee": "Current base fee is {{baseFee}} Gwei",
"popups_wallet_gas_max_priority_fee_too_low": "Max priority fee is too low for network conditions.",
"popups_wallet_gas_fee_settings_usd": " ≈ <span>{{usd}}</span>",
"popups_wallet_gas_fee_settings_gas_limit": "Gas Limit",
"popups_wallet_gas_fee_settings_max_priority_fee": "Max priority fee",
"popups_wallet_gas_fee_settings_max_fee": "Max fee",
"popups_wallet_gas_fee_settings_max_priority_fee": "Max Priority Fee",
"popups_wallet_gas_fee_settings_max_fee": "Max Fee",
"popups_wallet_gas_fee_settings_min_gas_limit_tips": "Gas limit must be at least {{limit}}",
"popups_wallet_speed_up_transaction_tips": "Spend more transaction fees to cancel the previous transaction.",
"popups_wallet_cancel_transaction_tips": "Spend more transaction fees to cancel the previous transaction.",
"popups_wallet_signature_request_title": "Signature Request",
"popups_wallet_signature_request": "Signature request",
"popups_wallet_signature_request_message": "Message",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { GasOptionType } from '@masknet/web3-shared-base'
import type { GasConfig } from '@masknet/web3-shared-evm'
import { Typography, useTheme } from '@mui/material'
import { Box } from '@mui/system'
import { memo, useCallback, useMemo, useState } from 'react'
import { useGasOptionsMenu } from '../../hook/useGasOptionsMenu.js'
import { useI18N } from '../../../../utils/i18n-next-ui.js'
import { Icons } from '@masknet/icons'

interface GasSettingMenuProps {
gas: string
onChange: (config: GasConfig) => void
}

export const GasSettingMenu = memo<GasSettingMenuProps>(function GasSettingMenu({ gas, onChange }) {
const { t } = useI18N()
const theme = useTheme()
const [gasOptionType, setGasOptionType] = useState<GasOptionType | undefined>()

const handleChange = useCallback(
(config: GasConfig, type?: GasOptionType) => {
if (type) setGasOptionType(type)
onChange(config)
},
[onChange],
)

const [menu, openMenu] = useGasOptionsMenu(gas, handleChange)

const gasOptionName = useMemo(() => {
switch (gasOptionType) {
case GasOptionType.FAST:
return t('popups_wallet_gas_fee_settings_instant')
case GasOptionType.NORMAL:
return t('popups_wallet_gas_fee_settings_high')
case GasOptionType.SLOW:
default:
return t('popups_wallet_gas_fee_settings_medium')
}
}, [gasOptionType])

return (
<>
<Box
py={0.5}
px={1.5}
border={`1px solid ${theme.palette.maskColor.line}`}
onClick={openMenu}
borderRadius={99}
display="inline-flex"
alignItems="center"
columnGap={0.5}>
<Typography fontWeight={700} lineHeight="18px" fontSize={14}>
{gasOptionName}
</Typography>
<Icons.Candle size={12} />
</Box>
{menu}
</>
)
})
133 changes: 133 additions & 0 deletions packages/mask/src/extension/popups/hook/useGasOptionsMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
import { useMenuConfig } from '@masknet/shared'
import { MenuItem, Typography } from '@mui/material'
import { useI18N } from '../../../utils/i18n-next-ui.js'
import { makeStyles } from '@masknet/theme'
import { useChainContext, useChainIdSupport, useGasOptions } from '@masknet/web3-hooks-base'
import { formatWeiToGwei, type GasConfig, type GasOption } from '@masknet/web3-shared-evm'
import { useCallback, useEffect } from 'react'
import { GasSettingModal } from '../modals/modals.js'
import { NetworkPluginID } from '@masknet/shared-base'
import { GasOptionType } from '@masknet/web3-shared-base'

const useStyles = makeStyles()((theme) => ({
paper: {
borderRadius: 16,
boxShadow: theme.palette.maskColor.bottomBg,
},
list: {
padding: theme.spacing(1.5),
},
item: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: theme.spacing(1, 0),
borderBottom: `1px solid ${theme.palette.maskColor.line}`,
minHeight: 'unset',
minWidth: 134,
cursor: 'pointer',
'&:first-child': {
paddingTop: 0,
},
'&:last-child': {
paddingBottom: 4,
border: 'unset',
},
},
optionName: {
fontSize: 14,
lineHeight: '18px',
fontWeight: 700,
},
optionValue: {
fontSize: 14,
lineHeight: '18px',
color: theme.palette.maskColor.third,
},
}))

export function useGasOptionsMenu(gas: string, callback: (config: GasConfig, type?: GasOptionType) => void) {
const { t } = useI18N()
const { classes } = useStyles()
const { value: gasOptions } = useGasOptions()

const { chainId } = useChainContext<NetworkPluginID.PLUGIN_EVM>()
const isSupport1559 = useChainIdSupport(NetworkPluginID.PLUGIN_EVM, 'EIP1559', chainId)

const handleClickCustom = useCallback(async () => {
const result = await GasSettingModal.openAndWaitForClose({
chainId,
config: { gas },
})
if (!result) return

callback(result)
}, [chainId, gas, callback])

const handleClick = useCallback(
(type?: GasOptionType, option?: GasOption) => {
if (!option) return
const config = isSupport1559
? {
maxPriorityFeePerGas: option.suggestedMaxPriorityFeePerGas,
maxFeePerGas: option.suggestedMaxFeePerGas,
}
: {
gasPrice: option.suggestedMaxFeePerGas,
}

callback(config, type)
},
[callback, isSupport1559],
)

// Set init gas option
useEffect(() => {
if (!gasOptions?.slow) return
handleClick(GasOptionType.SLOW, gasOptions.slow)
}, [gasOptions, handleClick])

return useMenuConfig(
[
<MenuItem
key="medium"
className={classes.item}
onClick={() => handleClick(GasOptionType.SLOW, gasOptions?.slow)}>
<Typography className={classes.optionName}>{t('popups_wallet_gas_fee_settings_medium')}</Typography>
<Typography className={classes.optionValue}>
{formatWeiToGwei(gasOptions?.slow.suggestedMaxFeePerGas ?? 0).toFixed(2)}
<Typography component="span">{t('wallet_transfer_gwei')}</Typography>
</Typography>
</MenuItem>,
<MenuItem
key="high"
className={classes.item}
onClick={() => handleClick(GasOptionType.NORMAL, gasOptions?.normal)}>
<Typography className={classes.optionName}>{t('popups_wallet_gas_fee_settings_high')}</Typography>
<Typography className={classes.optionValue}>
{formatWeiToGwei(gasOptions?.normal.suggestedMaxFeePerGas ?? 0).toFixed(2)}
<Typography component="span">{t('wallet_transfer_gwei')}</Typography>
</Typography>
</MenuItem>,
<MenuItem
key="instant"
className={classes.item}
onClick={() => handleClick(GasOptionType.FAST, gasOptions?.fast)}>
<Typography className={classes.optionName}>{t('popups_wallet_gas_fee_settings_instant')}</Typography>
<Typography className={classes.optionValue}>
{formatWeiToGwei(gasOptions?.fast.suggestedMaxFeePerGas ?? 0).toFixed(2)}
<Typography component="span">{t('wallet_transfer_gwei')}</Typography>
</Typography>
</MenuItem>,
<MenuItem key="custom" className={classes.item} onClick={handleClickCustom}>
<Typography className={classes.optionName}>{t('popups_wallet_gas_fee_settings_custom')}</Typography>
</MenuItem>,
],
{
classes: {
paper: classes.paper,
list: classes.list,
},
},
)
}
Loading

0 comments on commit 357f049

Please sign in to comment.