-
Notifications
You must be signed in to change notification settings - Fork 311
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: gas setting * fix: bugfix * fix: add rule * feat: support replace transaction * chore: code style
- Loading branch information
1 parent
dafa792
commit 357f049
Showing
13 changed files
with
584 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
packages/mask/src/extension/popups/components/GasSettingMenu/index.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
133
packages/mask/src/extension/popups/hook/useGasOptionsMenu.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
}, | ||
}, | ||
) | ||
} |
Oops, something went wrong.