Skip to content

Commit

Permalink
feat: support gasLimit and gasPrice edit in send tx (#11470)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jack-Works committed Mar 6, 2024
1 parent e054e3c commit 33f4ebf
Show file tree
Hide file tree
Showing 32 changed files with 242 additions and 203 deletions.
5 changes: 0 additions & 5 deletions packages/mask/entry-sdk/README.md
Expand Up @@ -5,11 +5,6 @@ The list is built from what [MetaMask supported](https://docs.metamask.io/wallet

- <https://ethereum.github.io/execution-apis/api-documentation/>

## Need revisit

- [ ] TransactionDescriptorType.DEPLOYMENT failed. Open <https://metamask.github.io/test-dapp/> and try TOKEN/NFTs deploy
- [ ] Sign In With Ethereum (A special extension of personal_sign method?)

## Read ETH methods

- [x] net_version
Expand Down
112 changes: 56 additions & 56 deletions packages/mask/popups/components/GasSettingMenu/index.tsx
@@ -1,8 +1,8 @@
import { memo, useCallback, useEffect, useMemo, useState } from 'react'
import { memo, useCallback, useMemo, useState } from 'react'
import { noop } from 'lodash-es'
import { BigNumber } from 'bignumber.js'
import { Box } from '@mui/system'
import { Typography, useTheme } from '@mui/material'
import { Button, Typography, useTheme } from '@mui/material'
import { Icons } from '@masknet/icons'
import { FormattedBalance, FormattedCurrency, useGasCurrencyMenu } from '@masknet/shared'
import { NetworkPluginID } from '@masknet/shared-base'
Expand All @@ -11,18 +11,19 @@ import {
useChainIdSupport,
useFungibleToken,
useFungibleTokenPrice,
useGasLimitRange,
useGasOptions,
useNativeTokenAddress,
} from '@masknet/web3-hooks-base'
import { GasOptionType, ZERO, formatBalance, formatCurrency, scale10, toFixed } from '@masknet/web3-shared-base'
import { type EIP1559GasConfig, type GasConfig, type ChainId, formatWeiToEther } from '@masknet/web3-shared-evm'
import { type GasConfig, type ChainId, formatWeiToEther } from '@masknet/web3-shared-evm'
import { useMaskSharedTrans } from '../../../shared-ui/index.js'
import { useGasOptionsMenu } from '../../hooks/index.js'
import { useGasRatio } from '../../hooks/useGasRatio.js'

interface GasSettingMenuProps {
minimumGas: string
initConfig?: GasConfig
defaultGasLimit: string | undefined
defaultGasConfig?: GasConfig
defaultChainId?: ChainId
disable?: boolean
onChange?: (config: GasConfig) => void
Expand All @@ -34,9 +35,9 @@ interface GasSettingMenuProps {
}

export const GasSettingMenu = memo<GasSettingMenuProps>(function GasSettingMenu({
minimumGas,
defaultGasLimit,
defaultChainId,
initConfig,
defaultGasConfig,
paymentToken,
disable,
allowMaskAsGas,
Expand All @@ -46,10 +47,15 @@ export const GasSettingMenu = memo<GasSettingMenuProps>(function GasSettingMenu(
}) {
const t = useMaskSharedTrans()
const theme = useTheme()

const { chainId } = useChainContext<NetworkPluginID.PLUGIN_EVM>({ chainId: defaultChainId })
const gasRatio = useGasRatio(paymentToken)
const [gasConfig = initConfig, setGasConfig] = useState<GasConfig | undefined>()
const [gasConfig, setGasConfig] = useState(defaultGasConfig)
const [, chainDefaultGasLimit] = useGasLimitRange(NetworkPluginID.PLUGIN_EVM, { chainId })
const gasLimit = gasConfig?.gas || chainDefaultGasLimit

const [gasOptionType, setGasOptionType] = useState<GasOptionType | undefined>(
initConfig?.gasOptionType ?? GasOptionType.SLOW,
gasConfig?.gasOptionType ?? GasOptionType.SLOW,
)

const handleChange = useCallback(
Expand All @@ -61,7 +67,7 @@ export const GasSettingMenu = memo<GasSettingMenuProps>(function GasSettingMenu(
[onChange],
)

const [menu, openMenu] = useGasOptionsMenu(minimumGas, !disable ? handleChange : noop, paymentToken)
const [menu, openMenu] = useGasOptionsMenu(gasLimit, !disable ? handleChange : noop, paymentToken)

const [paymentTokenMenu, openPaymentTokenMenu] = useGasCurrencyMenu(
NetworkPluginID.PLUGIN_EVM,
Expand All @@ -71,8 +77,26 @@ export const GasSettingMenu = memo<GasSettingMenuProps>(function GasSettingMenu(

const { data: gasOptions } = useGasOptions()

const { chainId } = useChainContext<NetworkPluginID.PLUGIN_EVM>({ chainId: defaultChainId })
const isSupport1559 = useChainIdSupport(NetworkPluginID.PLUGIN_EVM, 'EIP1559', chainId)
{
const isSupport1559 = useChainIdSupport(NetworkPluginID.PLUGIN_EVM, 'EIP1559', chainId)
if (gasOptions && !gasConfig) {
const target = gasOptions[GasOptionType.SLOW]
setGasConfig(
isSupport1559 ?
{
gasOptionType: GasOptionType.SLOW,
maxPriorityFeePerGas: target.suggestedMaxPriorityFeePerGas,
maxFeePerGas: target.suggestedMaxFeePerGas,
gas: defaultGasLimit,
}
: {
gasOptionType: GasOptionType.SLOW,
gasPrice: target.suggestedMaxFeePerGas,
gas: defaultGasLimit,
},
)
}
}

const nativeTokenAddress = useNativeTokenAddress(NetworkPluginID.PLUGIN_EVM, { chainId })

Expand Down Expand Up @@ -102,40 +126,13 @@ export const GasSettingMenu = memo<GasSettingMenuProps>(function GasSettingMenu(
}, [gasOptionType])

const totalGas = useMemo(() => {
if (!gasConfig) return ZERO
const result = new BigNumber(
(isSupport1559 ? (gasConfig as EIP1559GasConfig).maxFeePerGas : gasConfig.gasPrice) || ZERO,
).times(minimumGas)

if (!gasRatio) return toFixed(result, 0)
return toFixed(result.multipliedBy(gasRatio), 0)
}, [gasConfig, minimumGas, gasRatio])

// If there is no init configuration, set a default config
useEffect(() => {
if (!!initConfig || !gasOptions || !onChange) return
const target = gasOptions[GasOptionType.SLOW]
const result =
isSupport1559 ?
{
gasOptionType: GasOptionType.SLOW,
maxPriorityFeePerGas: target.suggestedMaxPriorityFeePerGas,
maxFeePerGas: target.suggestedMaxFeePerGas,
gas: minimumGas,
}
: {
gasOptionType: GasOptionType.SLOW,
gasPrice: target.suggestedMaxFeePerGas,
gas: minimumGas,
}

setGasConfig((prev) => {
if (prev) return
return result
})

onChange(result)
}, [onChange, initConfig, gasOptions, isSupport1559, minimumGas])
if (!gasConfig || !gasLimit) return ZERO
const maxGasPrice = 'maxFeePerGas' in gasConfig ? gasConfig.maxFeePerGas : gasConfig.gasPrice
if (!maxGasPrice) return ZERO
const maxPriceUsed = new BigNumber(maxGasPrice).times(gasLimit)
if (!gasRatio) return toFixed(maxPriceUsed, 0)
return toFixed(maxPriceUsed.multipliedBy(gasRatio), 0)
}, [gasConfig, gasLimit, gasRatio])

return (
<Box display="flex" alignItems="center">
Expand All @@ -161,20 +158,23 @@ export const GasSettingMenu = memo<GasSettingMenuProps>(function GasSettingMenu(
/>
</Typography>
{!disable ?
<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}>
<Button
variant="text"
sx={{
py: 0.5,
px: 1.5,
border: `1px solid ${theme.palette.maskColor.line}`,
borderRadius: 99,
display: 'inline-flex',
alignItems: 'center',
columnGap: 0.5,
}}
onClick={openMenu}>
<Typography fontWeight={700} lineHeight="18px" fontSize={14}>
{gasOptionName}
</Typography>
<Icons.Candle size={12} />
</Box>
</Button>
: null}
{owner && allowMaskAsGas ?
<>
Expand Down
20 changes: 9 additions & 11 deletions packages/mask/popups/components/TransactionPreview/index.tsx
Expand Up @@ -231,17 +231,15 @@ export const TransactionPreview = memo<TransactionPreviewProps>(function Transac
</Box>
<Box mt={3.75} display="flex" justifyContent="space-between" alignItems="center">
<Typography className={classes.gasFeeTitle}>{t.popups_wallet_gas_fee()}</Typography>
{transaction.computedPayload.gas && !!initConfig ?
<GasSettingMenu
minimumGas={transaction.computedPayload.gas}
initConfig={initConfig}
onChange={onConfigChange}
paymentToken={paymentToken}
allowMaskAsGas={transaction.allowMaskAsGas}
owner={transaction.owner}
onPaymentTokenChange={onPaymentTokenChange}
/>
: null}
<GasSettingMenu
defaultGasLimit={transaction.computedPayload.gas}
defaultGasConfig={initConfig}
onChange={onConfigChange}
paymentToken={paymentToken}
allowMaskAsGas={transaction.allowMaskAsGas}
owner={transaction.owner}
onPaymentTokenChange={onPaymentTokenChange}
/>
</Box>
</Box>
)
Expand Down
4 changes: 2 additions & 2 deletions packages/mask/popups/components/UnlockERC20Token/index.tsx
Expand Up @@ -269,8 +269,8 @@ export const UnlockERC20Token = memo<UnlockERC20TokenProps>(function UnlockERC20
<Typography className={classes.gasFeeTitle}>{t.popups_wallet_gas_fee()}</Typography>
{transaction.computedPayload.gas && initConfig ?
<GasSettingMenu
minimumGas={transaction.computedPayload.gas}
initConfig={initConfig}
defaultGasLimit={transaction.computedPayload.gas}
defaultGasConfig={initConfig}
onChange={onConfigChange}
onPaymentTokenChange={onPaymentTokenChange}
owner={transaction.owner}
Expand Down
4 changes: 2 additions & 2 deletions packages/mask/popups/components/UnlockERC721Token/index.tsx
Expand Up @@ -225,8 +225,8 @@ export const UnlockERC721Token = memo<UnlockERC721TokenProps>(function UnlockERC
<Typography className={classes.gasFeeTitle}>{t.popups_wallet_gas_fee()}</Typography>
{transaction.computedPayload.gas && initConfig ?
<GasSettingMenu
minimumGas={transaction.computedPayload.gas}
initConfig={initConfig}
defaultGasLimit={transaction.computedPayload.gas}
defaultGasConfig={initConfig}
onChange={onConfigChange}
onPaymentTokenChange={onPaymentTokenChange}
owner={transaction.owner}
Expand Down
49 changes: 22 additions & 27 deletions packages/mask/popups/hooks/useGasOptionsMenu.tsx
Expand Up @@ -3,7 +3,7 @@ import { NetworkPluginID } from '@masknet/shared-base'
import { makeStyles } from '@masknet/theme'
import { useChainContext, useChainIdSupport, useGasOptions } from '@masknet/web3-hooks-base'
import { GasOptionType } from '@masknet/web3-shared-base'
import { formatWeiToGwei, type EIP1559GasConfig, type GasConfig, type GasOption } from '@masknet/web3-shared-evm'
import { formatWeiToGwei, type GasConfig, type GasOption } from '@masknet/web3-shared-evm'
import { MenuItem, Typography } from '@mui/material'
import { useCallback, useState } from 'react'
import { useMaskSharedTrans } from '../../shared-ui/index.js'
Expand All @@ -15,27 +15,20 @@ const useStyles = makeStyles()((theme) => ({
boxShadow: theme.palette.maskColor.bottomBg,
},
list: {
padding: theme.spacing(1.5),
padding: theme.spacing(0.5, 0),
},
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-of-type': {
paddingTop: 0,
minHeight: 38,
'& > p:first-of-type': {
marginRight: 12,
},
'&:last-of-type': {
paddingBottom: 4,
border: 'unset',
},
'&.Mui-focusVisible': {
backgroundColor: 'transparent',
},
},
optionName: {
fontSize: 14,
Expand All @@ -50,7 +43,7 @@ const useStyles = makeStyles()((theme) => ({
}))

export function useGasOptionsMenu(
minimumGas: string,
gasLimit: string | undefined,
callback: (config: GasConfig, type?: GasOptionType) => void,
paymentToken?: string,
) {
Expand All @@ -66,24 +59,26 @@ export function useGasOptionsMenu(
const handleClickCustom = useCallback(async () => {
const result = await GasSettingModal.openAndWaitForClose({
chainId,
config: { gas: minimumGas, paymentToken, ...customGasConfig },
config: { gasLimit, paymentToken, ...customGasConfig },
})
if (!result) return

setCustomGasConfig({
...result,
gasPrice: result.gasPrice ? formatWeiToGwei(result.gasPrice).toFixed(2) : undefined,
maxFeePerGas:
(result as EIP1559GasConfig).maxFeePerGas ?
formatWeiToGwei((result as EIP1559GasConfig).maxFeePerGas).toFixed(2)
: '',
maxPriorityFeePerGas:
(result as EIP1559GasConfig).maxPriorityFeePerGas ?
formatWeiToGwei((result as EIP1559GasConfig).maxPriorityFeePerGas).toFixed(2)
: '',
})
if ('maxFeePerGas' in result) {
setCustomGasConfig({
...result,
gasPrice: result.gasPrice ? formatWeiToGwei(result.gasPrice).toFixed(2) : undefined,
maxFeePerGas: result.maxFeePerGas ? formatWeiToGwei(result.maxFeePerGas).toFixed(2) : '',
maxPriorityFeePerGas:
result.maxPriorityFeePerGas ? formatWeiToGwei(result.maxPriorityFeePerGas).toFixed(2) : '',
})
} else {
setCustomGasConfig({
...result,
gasPrice: formatWeiToGwei(result.gasPrice).toFixed(2),
})
}
callback(result)
}, [chainId, minimumGas, callback, customGasConfig, paymentToken])
}, [chainId, gasLimit, callback, customGasConfig, paymentToken])

const handleClick = useCallback(
(type?: GasOptionType, option?: GasOption) => {
Expand Down

0 comments on commit 33f4ebf

Please sign in to comment.