Skip to content

Commit

Permalink
fix: default mask availabel balance (#8978)
Browse files Browse the repository at this point in the history
* fix: default mask availabel balance

* chore: typo
  • Loading branch information
nuanyang233 committed Mar 7, 2023
1 parent 80de5b4 commit 59453e4
Show file tree
Hide file tree
Showing 6 changed files with 189 additions and 19 deletions.
@@ -1,5 +1,5 @@
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useUpdateEffect } from 'react-use'
import { useAsync, useUpdateEffect } from 'react-use'
import { BigNumber } from 'bignumber.js'
import { Icons } from '@masknet/icons'
import { useGasLimit, useTokenTransferCallback } from '@masknet/web3-hooks-evm'
Expand All @@ -12,11 +12,23 @@ import {
useWeb3State,
useNativeToken,
useNativeTokenPrice,
useMaskTokenAddress,
useWallet,
} from '@masknet/web3-hooks-base'
import { FormattedAddress, TokenAmountPanel, useSelectFungibleToken } from '@masknet/shared'
import { NetworkPluginID } from '@masknet/shared-base'
import { MaskColorVar, MaskTextField } from '@masknet/theme'
import { TokenType, FungibleToken, isGreaterThan, isZero, multipliedBy, rightShift } from '@masknet/web3-shared-base'
import {
TokenType,
FungibleToken,
isGreaterThan,
isZero,
multipliedBy,
rightShift,
isSameAddress,
minus,
toFixed,
} from '@masknet/web3-shared-base'
import {
SchemaType,
formatWeiToEther,
Expand All @@ -26,11 +38,14 @@ import {
isValidAddress,
NetworkType,
isNativeTokenAddress,
DepositPaymaster,
EIP1559GasConfig,
} from '@masknet/web3-shared-evm'
import { Tune as TuneIcon } from '@mui/icons-material'
import { Box, Button, IconButton, Link, Popover, Stack, Typography } from '@mui/material'
import { useDashboardI18N } from '../../../../locales/index.js'
import { useGasConfig } from '../../hooks/useGasConfig.js'
import { SmartPayBundler } from '@masknet/web3-providers'

export interface TransferERC20Props {
token: FungibleToken<ChainId, SchemaType>
Expand All @@ -40,6 +55,7 @@ const GAS_LIMIT = 21000

export const TransferERC20 = memo<TransferERC20Props>(({ token }) => {
const t = useDashboardI18N()
const wallet = useWallet()
const anchorEl = useRef<HTMLDivElement | null>(null)
const [amount, setAmount] = useState('')
const [address, setAddress] = useState('')
Expand Down Expand Up @@ -108,14 +124,50 @@ export const TransferERC20 = memo<TransferERC20Props>(({ token }) => {
}, [gasLimit, gasPrice, maxFee, is1559Supported])
const gasFeeInUsd = formatWeiToEther(gasFee).multipliedBy(nativeTokenPrice.value ?? 0)

// #region hack for smartPay, will be removed
const maskTokenAddress = useMaskTokenAddress()

const { value: smartPayConfig } = useAsync(async () => {
const smartPayChainId = await SmartPayBundler.getSupportedChainId()
const depositPaymaster = new DepositPaymaster(smartPayChainId)
const ratio = await depositPaymaster.getRatio()

return {
ratio,
smartPayChainId,
}
}, [])

const actualBalance = useMemo(() => {
if (
!wallet?.owner ||
chainId !== smartPayConfig?.smartPayChainId ||
!isSameAddress(selectedToken?.address, maskTokenAddress)
)
return tokenBalance

return toFixed(
minus(
tokenBalance,

new BigNumber((gasConfig as EIP1559GasConfig).maxFeePerGas)
.multipliedBy(!isZero(gasLimit) ? gasLimit : '150000')
.integerValue()
.multipliedBy(smartPayConfig?.ratio ?? 1),
),
0,
)
}, [gasConfig, wallet, selectedToken?.address, maskTokenAddress, smartPayConfig, chainId, tokenBalance, gasLimit])
// #endregion

const maxAmount = useMemo(() => {
const price = is1559Supported && maxFee ? new BigNumber(maxFee) : gasPrice
const gasFee = multipliedBy(gasLimit, price)

let amount_ = new BigNumber(tokenBalance || '0')
let amount_ = new BigNumber(actualBalance || '0')
amount_ = selectedToken.schema === SchemaType.Native ? amount_.minus(gasFee) : amount_
return BigNumber.max(0, amount_).toFixed()
}, [tokenBalance, gasPrice, selectedToken?.type, amount, gasLimit, maxFee, is1559Supported])
}, [actualBalance, gasPrice, selectedToken?.type, amount, gasLimit, maxFee, is1559Supported])

const [{ loading: isTransferring }, transferCallback] = useTokenTransferCallback(tokenType, selectedToken.address)

Expand Down Expand Up @@ -262,7 +314,7 @@ export const TransferERC20 = memo<TransferERC20Props>(({ token }) => {
<TokenAmountPanel
amount={amount}
maxAmount={maxAmount}
balance={tokenBalance}
balance={actualBalance}
label={t.wallets_transfer_amount()}
token={selectedToken}
onAmountChange={setAmount}
Expand Down
Expand Up @@ -8,6 +8,7 @@ import { EthereumAddress } from 'wallet.ts'
import { BigNumber } from 'bignumber.js'
import {
ChainId,
DepositPaymaster,
explorerResolver,
formatEthereumAddress,
formatGweiToEther,
Expand All @@ -26,8 +27,10 @@ import {
isPositive,
isSameAddress,
isZero,
minus,
multipliedBy,
rightShift,
toFixed,
} from '@masknet/web3-shared-base'
import { Controller, FormProvider, useForm, useFormContext } from 'react-hook-form'
import { zodResolver } from '@hookform/resolvers/zod'
Expand All @@ -51,13 +54,16 @@ import {
useWeb3Connection,
useGasOptions,
useNetworkContext,
useMaskTokenAddress,
} from '@masknet/web3-hooks-base'
import { AccountItem } from './AccountItem.js'
import { TransferAddressError } from '../type.js'
import { useI18N } from '../../../../../utils/index.js'
import { useGasLimit, useTokenTransferCallback } from '@masknet/web3-hooks-evm'
import Services from '../../../../service.js'
import { Trans } from 'react-i18next'
import { useContainer } from 'unstated-next'
import { PopupContext } from '../../../hook/usePopupContext.js'

const useStyles = makeStyles()({
container: {
Expand Down Expand Up @@ -205,6 +211,8 @@ export const Transfer1559 = memo<Transfer1559Props>(({ selectedAsset, openAssetM
message: string
} | null>()

const { smartPayChainId } = useContainer(PopupContext)

const { value: etherPrice } = useNativeTokenPrice(NetworkPluginID.PLUGIN_EVM, {
chainId: nativeToken?.chainId,
})
Expand Down Expand Up @@ -310,7 +318,7 @@ export const Transfer1559 = memo<Transfer1559Props>(({ selectedAsset, openAssetM
},
})

const [address, amount, maxFeePerGas] = methods.watch(['address', 'amount', 'maxFeePerGas'])
const [address, amount, maxFeePerGas, gasLimit] = methods.watch(['address', 'amount', 'maxFeePerGas', 'gasLimit'])

// #region resolve ENS domain
const {
Expand Down Expand Up @@ -389,12 +397,46 @@ export const Transfer1559 = memo<Transfer1559Props>(({ selectedAsset, openAssetM
selectedAsset?.address ?? '',
)

// #region hack for smartPay, will be removed
const maskTokenAddress = useMaskTokenAddress()
const { value: ratio } = useAsync(async () => {
if (!smartPayChainId) return
const depositPaymaster = new DepositPaymaster(smartPayChainId)
return depositPaymaster.getRatio()
}, [smartPayChainId])

const actualSelected = useMemo(() => {
if (!selectedAsset) return
if (
!wallet?.owner ||
chainId !== smartPayChainId ||
!isSameAddress(selectedAsset?.address, maskTokenAddress) ||
!ratio
)
return selectedAsset

return {
...selectedAsset,
balance: toFixed(
minus(
selectedAsset?.balance,
new BigNumber(formatGweiToWei(maxFeePerGas))
.multipliedBy(!isZero(gasLimit) ? gasLimit : 150000)
.integerValue()
.multipliedBy(ratio),
),
0,
),
}
}, [gasLimit, maxFeePerGas, selectedAsset, maskTokenAddress, smartPayChainId, chainId, wallet?.owner, ratio])
// #endregion

const maxAmount = useMemo(() => {
const gasFee = formatGweiToWei(maxFeePerGas || 0).multipliedBy(minGasLimit ?? MIN_GAS_LIMIT)
let amount_ = new BigNumber(tokenBalance ?? 0)
amount_ = selectedAsset?.schema === SchemaType.Native ? amount_.minus(gasFee) : amount_
return formatBalance(BigNumber.max(0, amount_).toFixed(), selectedAsset?.decimals)
}, [selectedAsset, maxFeePerGas, minGasLimit, tokenBalance])
amount_ = actualSelected?.schema === SchemaType.Native ? amount_.minus(gasFee) : amount_
return formatBalance(BigNumber.max(0, amount_).toFixed(), actualSelected?.decimals)
}, [actualSelected, maxFeePerGas, minGasLimit, tokenBalance])

// #region set default gasLimit
useUpdateEffect(() => {
Expand Down Expand Up @@ -536,7 +578,7 @@ export const Transfer1559 = memo<Transfer1559Props>(({ selectedAsset, openAssetM
openAssetMenu={openAssetMenu}
handleMaxClick={handleMaxClick}
etherPrice={etherPrice ?? 0}
selectedAsset={selectedAsset}
selectedAsset={actualSelected}
handleCancel={handleCancel}
handleConfirm={methods.handleSubmit(onSubmit)}
confirmLoading={loading}
Expand Down
Expand Up @@ -14,10 +14,20 @@ export interface InputTokenPanelProps extends withClasses<'root'> {
token?: Web3Helper.FungibleTokenAll | null
onAmountChange: (amount: string) => void
SelectTokenChip?: Partial<SelectTokenChipProps>
isAvailableBalance?: boolean
}

export const InputTokenPanel = memo<InputTokenPanelProps>(
({ chainId, token, balance, onAmountChange, amount, SelectTokenChip: SelectTokenChipProps, maxAmount }) => {
({
chainId,
token,
balance,
onAmountChange,
amount,
SelectTokenChip: SelectTokenChipProps,
maxAmount,
isAvailableBalance,
}) => {
const { pluginID } = useNetworkContext()
const { Others } = useWeb3State()
const { value: tokenPrice = 0 } = useFungibleTokenPrice(pluginID, token?.address.toLowerCase())
Expand All @@ -29,6 +39,7 @@ export const InputTokenPanel = memo<InputTokenPanelProps>(

return (
<InputTokenPanelUI
isAvailableBalance={isAvailableBalance}
balance={
Others?.isNativeTokenAddress(token?.address) ? formatEtherToWei(maxAmount).toString() : balance
}
Expand Down
Expand Up @@ -178,6 +178,7 @@ export interface AllTradeFormProps extends withClasses<'root'> {
onSwitch: () => void
settings?: boolean
gasConfig?: GasConfig
isSmartPay: boolean
}

export const TradeForm = memo<AllTradeFormProps>(
Expand All @@ -191,7 +192,7 @@ export const TradeForm = memo<AllTradeFormProps>(
inputTokenBalance,
focusedTrade,
onFocusedTradeChange,

isSmartPay,
gasPrice,
onSwitch,
settings,
Expand Down Expand Up @@ -349,6 +350,7 @@ export const TradeForm = memo<AllTradeFormProps>(
<>
<Box className={classes.root}>
<InputTokenPanel
isAvailableBalance={isSmartPay}
chainId={chainId}
amount={inputAmount}
balance={inputTokenBalanceAmount.toFixed()}
Expand Down

0 comments on commit 59453e4

Please sign in to comment.