From cae735e218131019926c523f83e544662b4f556c Mon Sep 17 00:00:00 2001 From: heisenberg <110591045+heisenberg-2077@users.noreply.github.com> Date: Fri, 26 Apr 2024 13:47:26 +0800 Subject: [PATCH] fix: sign page bugs (#2236) * fix: enhancement of number input checking rule * fix: remove the title attribute of gasSelector * fix: gas ui * feat: useApprovalUtils * fix: remove screen height * fix: remove --- src/background/controller/provider/rpcFlow.ts | 3 +- src/constant/regexp.ts | 13 ++++++ src/ui/component/TokenAmountInput/index.tsx | 9 +++- .../Actions/components/AddressMemo.tsx | 17 ++++--- .../components/TxComponents/GasSelecter.tsx | 25 +++++------ .../views/Approval/hooks/useApprovalAlias.ts | 44 +++++++++++++++++++ .../views/Approval/hooks/useApprovalUtils.tsx | 30 +++++++++++++ src/ui/views/Approval/index.tsx | 14 +++--- .../SendToken/components/GasSelector.tsx | 5 ++- 9 files changed, 130 insertions(+), 30 deletions(-) create mode 100644 src/constant/regexp.ts create mode 100644 src/ui/views/Approval/hooks/useApprovalAlias.ts create mode 100644 src/ui/views/Approval/hooks/useApprovalUtils.tsx diff --git a/src/background/controller/provider/rpcFlow.ts b/src/background/controller/provider/rpcFlow.ts index 75c2106e9de..cca79de947e 100644 --- a/src/background/controller/provider/rpcFlow.ts +++ b/src/background/controller/provider/rpcFlow.ts @@ -14,7 +14,6 @@ import * as Sentry from '@sentry/browser'; import stats from '@/stats'; import { addHexPrefix, stripHexPrefix } from 'ethereumjs-util'; import { findChain } from '@/utils/chain'; -import browser from 'webextension-polyfill'; const isSignApproval = (type: string) => { const SIGN_APPROVALS = ['SignText', 'SignTypedData', 'SignTx']; @@ -25,7 +24,7 @@ const lockedOrigins = new Set(); const connectOrigins = new Set(); const getScreenAvailHeight = async () => { - return (await browser.windows.getCurrent()).height || 1000; + return 1000; }; const flow = new PromiseFlow<{ diff --git a/src/constant/regexp.ts b/src/constant/regexp.ts new file mode 100644 index 00000000000..95463017c1f --- /dev/null +++ b/src/constant/regexp.ts @@ -0,0 +1,13 @@ +/** + * Regex for input number + * 1. Can't have more than one dot + * 2. Can't have more than one leading zero + * 3. Can't have non-numeric characters + */ +export const INPUT_NUMBER_RE = /^(?!0{2,})[0-9]*(?!.*\..*\.)[0-9.]*$/; + +// filter start with 0 or 0. +// replace start with . to 0. +export const filterNumber = (value: string = '') => { + return value.replace(/^0*(\d+)/, '$1').replace(/^\./, '0.'); +}; diff --git a/src/ui/component/TokenAmountInput/index.tsx b/src/ui/component/TokenAmountInput/index.tsx index 672057cd3de..31b43e542b5 100644 --- a/src/ui/component/TokenAmountInput/index.tsx +++ b/src/ui/component/TokenAmountInput/index.tsx @@ -21,6 +21,7 @@ import { abstractTokenToTokenItem, getTokenSymbol } from 'ui/utils/token'; import TokenSelector, { TokenSelectorProps } from '../TokenSelector'; import TokenWithChain from '../TokenWithChain'; import './style.less'; +import { INPUT_NUMBER_RE, filterNumber } from '@/constant/regexp'; interface TokenAmountInputProps { token: TokenItem; @@ -166,6 +167,12 @@ const TokenAmountInput = ({ const valueNum = Number(value); + const handleChange = (e: React.ChangeEvent) => { + if (INPUT_NUMBER_RE.test(e.target.value)) { + onChange?.(filterNumber(e.target.value)); + } + }; + return (
@@ -186,7 +193,7 @@ const TokenAmountInput = ({ placeholder="0" className={clsx(!valueNum && 'h-[100%]')} value={value} - onChange={(e) => onChange && onChange(e.target.value)} + onChange={handleChange} title={value} /> {inlinePrize && ( diff --git a/src/ui/views/Approval/components/Actions/components/AddressMemo.tsx b/src/ui/views/Approval/components/Actions/components/AddressMemo.tsx index cb2afea872d..c5808010880 100644 --- a/src/ui/views/Approval/components/Actions/components/AddressMemo.tsx +++ b/src/ui/views/Approval/components/Actions/components/AddressMemo.tsx @@ -1,20 +1,25 @@ -import React, { useRef } from 'react'; +import React, { useEffect, useRef } from 'react'; import { useTranslation } from 'react-i18next'; import { Button, Form, Input } from 'antd'; import { useForm } from 'antd/lib/form/Form'; import { Popup } from 'ui/component'; -import { useAlias } from '@/ui/utils'; import IconEdit from 'ui/assets/editpen.svg'; +import { useApprovalUtils } from '../../../hooks/useApprovalUtils'; const AddressMemo = ({ address }: { address: string }) => { - const [addressAlias, updateAlias] = useAlias(address); + const { alias } = useApprovalUtils(); + const addressAlias = alias.accountMap[address]?.alias; const inputRef = useRef(null); const [form] = useForm(); const { t } = useTranslation(); + useEffect(() => { + alias.add(address); + }, [address]); + const updateAddressMemo = ( alias: string | undefined, - update: (memo: string) => void + update: (addr: string, memo: string) => void ) => { form.setFieldsValue({ memo: alias, @@ -34,7 +39,7 @@ const AddressMemo = ({ address }: { address: string }) => { form .validateFields() .then((values) => { - return update(values.memo); + return update(address, values.memo); }) .then(() => { destroy(); @@ -80,7 +85,7 @@ const AddressMemo = ({ address }: { address: string }) => { return (
updateAddressMemo(addressAlias, updateAlias)} + onClick={() => updateAddressMemo(addressAlias, alias.update)} > {addressAlias || '-'} diff --git a/src/ui/views/Approval/components/TxComponents/GasSelecter.tsx b/src/ui/views/Approval/components/TxComponents/GasSelecter.tsx index 49e35141df2..8d9a7b07924 100644 --- a/src/ui/views/Approval/components/TxComponents/GasSelecter.tsx +++ b/src/ui/views/Approval/components/TxComponents/GasSelecter.tsx @@ -29,6 +29,7 @@ import { Chain } from '@debank/common'; import { getGasLevelI18nKey } from '@/ui/utils/trans'; import ThemeIcon from '@/ui/component/ThemeMode/ThemeIcon'; import { findChain } from '@/utils/chain'; +import { INPUT_NUMBER_RE, filterNumber } from '@/constant/regexp'; export interface GasSelectorResponse extends GasLevel { gasLimit: number; @@ -380,8 +381,8 @@ const GasSelector = ({ const handleCustomGasChange = (e: React.ChangeEvent) => { e.stopPropagation(); - if (/^\d*(\.\d*)?$/.test(e.target.value)) { - setCustomGas(e.target.value); + if (INPUT_NUMBER_RE.test(e.target.value)) { + setCustomGas(filterNumber(e.target.value)); } }; @@ -473,11 +474,8 @@ const GasSelector = ({ ) => { e.stopPropagation(); - if (/^\d*(\.\d*)?$/.test(e.target.value)) { - let value = e?.target?.value || ''; - if (value.trim() === '.') { - value = '0.'; - } + if (INPUT_NUMBER_RE.test(e.target.value)) { + const value = filterNumber(e.target.value); setCustomGas(value); const gasObj = { @@ -652,11 +650,11 @@ const GasSelector = ({ gas.error || !gas.success ? 'items-start mb-12' : 'mb-12' )} > -
+
{t('page.signTx.gasSelectorTitle')}
-
+
{disabled ? (
{t('page.signTx.noGasRequired')} @@ -669,15 +667,17 @@ const GasSelector = ({ ) : (
-
- +
+ {formatTokenAmount( new BigNumber(gas.gasCostAmount).toString(10), 8 )}{' '} {chain.nativeTokenSymbol} -   ≈${new BigNumber(gas.gasCostUsd).toFixed(2)} + +   ≈${new BigNumber(gas.gasCostUsd).toFixed(2)} + {L2_ENUMS.includes(chain.enum) && !CAN_ESTIMATE_L1_FEE_CHAINS.includes(chain.enum) && ( @@ -1070,7 +1070,6 @@ const GasSelectPanel = ({ 'custom-input': item.level === 'custom', active: selectedGas?.level === item.level, })} - title={new BigNumber(item.price / 1e9).toFixed()} > {item.level === 'custom' ? ( { + const [accounts, setAccounts] = React.useState([]); + const wallet = useWallet(); + + const accountMap = React.useMemo(() => { + return accounts.reduce((acc, account) => { + acc[account.address] = account; + return acc; + }, {} as Record); + }, [accounts]); + + const add = React.useCallback( + async (address: string) => { + if (accounts.some((account) => account.address === address)) { + return accounts; + } + const alias = await wallet.getAlianName(address); + setAccounts([...accounts, { address, alias }]); + }, + [accounts] + ); + + const update = React.useCallback((address: string, alias: string) => { + setAccounts((accounts) => { + return accounts.map((account) => { + if (account.address === address) { + wallet.updateAlianName(address, alias); + return { ...account, alias }; + } + return account; + }); + }); + }, []); + + return { accountMap, add, update }; +}; diff --git a/src/ui/views/Approval/hooks/useApprovalUtils.tsx b/src/ui/views/Approval/hooks/useApprovalUtils.tsx new file mode 100644 index 00000000000..1c9275dc43b --- /dev/null +++ b/src/ui/views/Approval/hooks/useApprovalUtils.tsx @@ -0,0 +1,30 @@ +import React, { createContext, useContext } from 'react'; +import { useApprovalAlias } from './useApprovalAlias'; + +/** + * useApprovalUtils + * @description some global state for approval page + */ +const useApprovalUtilsState = () => { + const alias = useApprovalAlias(); + + return { alias }; +}; + +const ApprovalUtilsContext = createContext< + ReturnType +>({} as any); + +export const useApprovalUtils = () => { + return useContext(ApprovalUtilsContext); +}; + +export const ApprovalUtilsProvider = ({ children }) => { + const value = useApprovalUtilsState(); + + return ( + + {children} + + ); +}; diff --git a/src/ui/views/Approval/index.tsx b/src/ui/views/Approval/index.tsx index 2310f544872..89fbe739255 100644 --- a/src/ui/views/Approval/index.tsx +++ b/src/ui/views/Approval/index.tsx @@ -3,7 +3,7 @@ import { useHistory } from 'react-router-dom'; import { Approval } from 'background/service/notification'; import { useWallet, useApproval } from 'ui/utils'; import { IExtractFromPromise } from '@/ui/utils/type'; - +import { ApprovalUtilsProvider } from './hooks/useApprovalUtils'; import * as ApprovalComponent from './components'; import './style.less'; @@ -49,11 +49,13 @@ const Approval: React.FC<{ return (
{approval && ( - + + + )}
); diff --git a/src/ui/views/SendToken/components/GasSelector.tsx b/src/ui/views/SendToken/components/GasSelector.tsx index 35b4d1658a0..8506151c6bd 100644 --- a/src/ui/views/SendToken/components/GasSelector.tsx +++ b/src/ui/views/SendToken/components/GasSelector.tsx @@ -10,6 +10,7 @@ import styled from 'styled-components'; import { BigNumber } from 'bignumber.js'; import { getGasLevelI18nKey } from '@/ui/utils/trans'; import { findChain } from '@/utils/chain'; +import { INPUT_NUMBER_RE, filterNumber } from '@/constant/regexp'; interface GasSelectorProps { chainId: number; @@ -71,8 +72,8 @@ const GasSelector = ({ const handleCustomGasChange = (e: React.ChangeEvent) => { e.stopPropagation(); - if (/^\d*(\.\d*)?$/.test(e.target.value)) { - setCustomGas(e.target.value); + if (INPUT_NUMBER_RE.test(e.target.value)) { + setCustomGas(filterNumber(e.target.value)); } };