From 59df4960f9b857e8e706e60d263141035ced0613 Mon Sep 17 00:00:00 2001 From: heisenberg <110591045+heisenberg-2077@users.noreply.github.com> Date: Fri, 20 Oct 2023 18:18:47 +0800 Subject: [PATCH] feat: import cobo arugs address by event (#1798) * feat: import cobo arugs address by event * fix: textarea * fix: style * fix: close notifaction * fix: remove check chain id * fix: ignore check * feat: update page-provider * fix: height * fix: chainId --- package.json | 2 +- .../controller/provider/controller.ts | 16 +++++++ src/background/controller/provider/index.ts | 14 ++++-- src/ui/component/AddAddressOptions/index.tsx | 47 +++++++++++++++++-- .../Approval/components/ImportAddress.tsx | 33 +++++++++++++ src/ui/views/Approval/components/index.ts | 1 + src/ui/views/ImportCoboArgus/AddressInput.tsx | 40 +++++++++++----- src/ui/views/ImportCoboArgus/Header.tsx | 18 ++++--- .../views/ImportCoboArgus/ImportCoboArgus.tsx | 40 +++++++++++++--- src/ui/views/ImportSuccess/index.tsx | 9 +++- yarn.lock | 8 ++-- 11 files changed, 186 insertions(+), 42 deletions(-) create mode 100644 src/ui/views/Approval/components/ImportAddress.tsx diff --git a/package.json b/package.json index d51cdbb1f0a..453a6148fe8 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "@rabby-wallet/eth-walletconnect-keyring": "^2.0.4-beta.0", "@rabby-wallet/eth-watch-keyring": "^1.0.0", "@rabby-wallet/gnosis-sdk": "^1.3.5", - "@rabby-wallet/page-provider": "^0.1.23-alpha.2", + "@rabby-wallet/page-provider": "^0.1.23", "@rabby-wallet/rabby-api": "^0.6.23", "@rabby-wallet/rabby-security-engine": "^1.1.16", "@rabby-wallet/rabby-swap": "^0.0.29", diff --git a/src/background/controller/provider/controller.ts b/src/background/controller/provider/controller.ts index bb2e07125cd..2a634425745 100644 --- a/src/background/controller/provider/controller.ts +++ b/src/background/controller/provider/controller.ts @@ -1257,6 +1257,22 @@ class ProviderController extends BaseController { data: { method: 'eth_getTransactionByHash', params: [hash] }, }); }; + + @Reflect.metadata('APPROVAL', [ + 'ImportAddress', + ({ data }) => { + if (!data.params[0]) { + throw ethErrors.rpc.invalidParams('params is required but got []'); + } + if (!data.params[0]?.chainId) { + throw ethErrors.rpc.invalidParams('chainId is required'); + } + }, + { height: 628 }, + ]) + walletImportAddress = async () => { + return null; + }; } export default new ProviderController(); diff --git a/src/background/controller/provider/index.ts b/src/background/controller/provider/index.ts index 39e0877fc88..08deb98f8a6 100644 --- a/src/background/controller/provider/index.ts +++ b/src/background/controller/provider/index.ts @@ -11,6 +11,8 @@ import { import rpcFlow from './rpcFlow'; import internalMethod from './internalMethod'; +const IGNORE_CHECK = ['wallet_importAddress']; + tab.on('tabRemove', (id) => { sessionService.deleteSession(id); }); @@ -24,11 +26,13 @@ export default async (req: ProviderRequest): Promise => { return internalMethod[method](req); } - const hasVault = keyringService.hasVault(); - if (!hasVault) { - throw ethErrors.provider.userRejectedRequest({ - message: 'wallet must has at least one account', - }); + if (!IGNORE_CHECK.includes(method)) { + const hasVault = keyringService.hasVault(); + if (!hasVault) { + throw ethErrors.provider.userRejectedRequest({ + message: 'wallet must has at least one account', + }); + } } return rpcFlow(req) as any; diff --git a/src/ui/component/AddAddressOptions/index.tsx b/src/ui/component/AddAddressOptions/index.tsx index c7ee7f815dc..d118240b795 100644 --- a/src/ui/component/AddAddressOptions/index.tsx +++ b/src/ui/component/AddAddressOptions/index.tsx @@ -1,5 +1,5 @@ import React, { useState } from 'react'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { openInternalPageInTab } from 'ui/utils/webapi'; import IconWalletConnect from 'ui/assets/walletlogo/walletconnect.svg'; @@ -36,7 +36,7 @@ const getSortNum = (s: string) => WALLET_SORT_SCORE[s] || 999999; const AddAddressOptions = () => { const history = useHistory(); const { t } = useTranslation(); - + const location = useLocation(); const wallet = useWallet(); const [selectedWalletType, setSelectedWalletType] = useState(''); @@ -101,7 +101,14 @@ const AddAddressOptions = () => { type Valueof = T[keyof T]; const connectRouter1 = React.useCallback( - (history, item: Valueof) => { + ( + history, + item: Valueof, + params?: { + address: string; + chainId: number; + } + ) => { if (item.connectType === 'BitBox02Connect') { openInternalPageInTab('import/hardware?connectType=BITBOX02'); } else if (item.connectType === 'GridPlusConnect') { @@ -130,6 +137,7 @@ const AddAddressOptions = () => { ) { history.push({ pathname: '/import/cobo-argus', + state: params, }); } else { history.push({ @@ -142,8 +150,13 @@ const AddAddressOptions = () => { }, [] ); - const connectRouter = (item: Valueof) => - handleRouter((h) => connectRouter1(h, item)); + const connectRouter = ( + item: Valueof, + params?: { + address: string; + chainId: number; + } + ) => handleRouter((h) => connectRouter1(h, item, params)); const brandWallet = React.useMemo( () => (Object.values(WALLET_BRAND_CONTENT) @@ -252,6 +265,30 @@ const AddAddressOptions = () => { [t] ); + const [preventMount, setPreventMount] = React.useState(true); + React.useEffect(() => { + if (location.state) { + const { type, address, chainId } = location.state as any; + const brandContentKey = Object.keys(WALLET_BRAND_CONTENT).find((key) => { + const item = WALLET_BRAND_CONTENT[key] as IWalletBrandContent; + return item.name === type; + }); + + if (brandContentKey) { + connectRouter(WALLET_BRAND_CONTENT[brandContentKey], { + address, + chainId, + }); + } else { + setPreventMount(false); + } + } else { + setPreventMount(false); + } + }, [location.state, connectRouter]); + + if (preventMount) return null; + return (
{[createIMportAddrList, centerList].map((items, index) => ( diff --git a/src/ui/views/Approval/components/ImportAddress.tsx b/src/ui/views/Approval/components/ImportAddress.tsx new file mode 100644 index 00000000000..40d70050a45 --- /dev/null +++ b/src/ui/views/Approval/components/ImportAddress.tsx @@ -0,0 +1,33 @@ +import React from 'react'; +import { useHistory } from 'react-router'; + +interface ConnectProps { + params: { + data: [ + { + type: string; + address: string; + chainId: number; + } + ]; + session: { + icon: string; + name: string; + origin: string; + }; + }; +} + +export const ImportAddress = ({ params }: ConnectProps) => { + const history = useHistory(); + const addressParams = params.data[0]; + + React.useEffect(() => { + history.replace({ + pathname: '/add-address', + state: addressParams, + }); + }, []); + + return null; +}; diff --git a/src/ui/views/Approval/components/index.ts b/src/ui/views/Approval/components/index.ts index e4935b3f8f8..be11fad4a95 100644 --- a/src/ui/views/Approval/components/index.ts +++ b/src/ui/views/Approval/components/index.ts @@ -12,3 +12,4 @@ export { default as AddAsset } from './AddAsset'; export { default as GetPublicKey } from './GetPublicKey'; export { default as Decrypt } from './Decrypt'; export { default as ETHSign } from './ETHSign'; +export { ImportAddress } from './ImportAddress'; diff --git a/src/ui/views/ImportCoboArgus/AddressInput.tsx b/src/ui/views/ImportCoboArgus/AddressInput.tsx index d870744ce8a..b8b2a41eb0e 100644 --- a/src/ui/views/ImportCoboArgus/AddressInput.tsx +++ b/src/ui/views/ImportCoboArgus/AddressInput.tsx @@ -22,19 +22,33 @@ export const AddressInput: React.FC = ({ return (
- - } - autoFocus - onChange={(v) => onChange(v.target.value)} - value={value} - placeholder={t('page.newAddress.coboSafe.inputSafeModuleAddress')} - className={clsx('rounded-[6px] py-16 px-12', { - 'border-gray-divider': !error, - 'border-red': error, - })} - /> +
+ {chain.name} + + onChange(v.target.value)} + value={value} + placeholder={t('page.newAddress.coboSafe.inputSafeModuleAddress')} + className="p-0 min-h-[22px]" + autoSize={{ + minRows: 1, + maxRows: 3, + }} + /> +
{error}
); diff --git a/src/ui/views/ImportCoboArgus/Header.tsx b/src/ui/views/ImportCoboArgus/Header.tsx index 6b8bf409749..af2c3cb3731 100644 --- a/src/ui/views/ImportCoboArgus/Header.tsx +++ b/src/ui/views/ImportCoboArgus/Header.tsx @@ -4,7 +4,9 @@ import { useHistory } from 'react-router-dom'; import IconBack from 'ui/assets/icon-back.svg'; import IconCoboArgus from 'ui/assets/walletlogo/CoboArgus.svg'; -export const Header: React.FC = ({ children }) => { +export const Header: React.FC<{ + hasBack?: boolean; +}> = ({ children, hasBack = true }) => { const history = useHistory(); const handleClickBack = () => { @@ -20,11 +22,15 @@ export const Header: React.FC = ({ children }) => { }; return (
- + {hasBack ? ( + + ) : ( +
+ )}
diff --git a/src/ui/views/ImportCoboArgus/ImportCoboArgus.tsx b/src/ui/views/ImportCoboArgus/ImportCoboArgus.tsx index f9d2e5ca5fa..bec7f9a9d17 100644 --- a/src/ui/views/ImportCoboArgus/ImportCoboArgus.tsx +++ b/src/ui/views/ImportCoboArgus/ImportCoboArgus.tsx @@ -5,15 +5,20 @@ import { AddressInput } from './AddressInput'; import { Button, message } from 'antd'; import clsx from 'clsx'; import { Header } from './Header'; -import { useWallet } from '@/ui/utils'; +import { useApproval, useWallet } from '@/ui/utils'; import { isAddress } from 'web3-utils'; import { SelectAddressPopup } from './SelectAddressPopup'; -import { useHistory } from 'react-router-dom'; +import { useHistory, useLocation } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; +import { findChainByID } from '@/utils/chain'; type Type = 'select-chain' | 'add-address' | 'select-address'; export const ImportCoboArgus = () => { + const { state } = useLocation<{ + address: string; + chainId: number | string; + }>(); const { t } = useTranslation(); const [selectedChain, setSelectedChain] = React.useState(); const [inputAddress, setInputAddress] = React.useState(''); @@ -23,6 +28,8 @@ export const ImportCoboArgus = () => { const [safeAddress, setSafeAddress] = React.useState(''); const wallet = useWallet(); const history = useHistory(); + const [hasImportError, setHasImportError] = React.useState(false); + const isByImportAddressEvent = !!state; const handleNext = React.useCallback(async () => { if (selectedChain && step === 'select-chain') { @@ -68,20 +75,39 @@ export const ImportCoboArgus = () => { }, }); } catch (e) { + setHasImportError(true); message.error(e.message); } }, [selectedChain, safeAddress, inputAddress]); + const [, , rejectApproval] = useApproval(); + const handleClose = React.useCallback(() => { + rejectApproval(); + }, [rejectApproval]); + + React.useEffect(() => { + if (!state) return; + const { chainId, address } = state; + const chain = findChainByID( + typeof chainId === 'number' ? chainId : parseInt(chainId, 10) + ); + + if (chain) { + setStep('add-address'); + setSelectedChain(chain.enum); + setInputAddress(address); + } + }, []); + return (
-
+
{step === 'select-chain' && t('page.newAddress.coboSafe.whichChainIsYourCoboAddressOn')} {(step === 'add-address' || step === 'select-address') && t('page.newAddress.coboSafe.addCoboArgusAddress')}
- -
+
{step === 'select-chain' && ( )} @@ -121,10 +147,10 @@ export const ImportCoboArgus = () => { } className="w-[200px] h-[44px] m-auto" type="primary" - onClick={handleNext} + onClick={hasImportError ? handleClose : handleNext} loading={isLoading} > - {t('global.next')} + {hasImportError ? t('global.ok') : t('global.next')}
diff --git a/src/ui/views/ImportSuccess/index.tsx b/src/ui/views/ImportSuccess/index.tsx index 7f0174d18cb..af74ba7500f 100644 --- a/src/ui/views/ImportSuccess/index.tsx +++ b/src/ui/views/ImportSuccess/index.tsx @@ -5,7 +5,7 @@ import { matomoRequestEvent } from '@/utils/matomo-request'; import { sortBy } from 'lodash'; import { StrayPageWithButton } from 'ui/component'; import AddressItem from 'ui/component/AddressList/AddressItem'; -import { getUiType } from 'ui/utils'; +import { getUiType, useApproval } from 'ui/utils'; import { Account } from 'background/service/preference'; import clsx from 'clsx'; import stats from '@/stats'; @@ -45,6 +45,7 @@ const ImportSuccess = ({ isPopup = false }: { isPopup?: boolean }) => { isMnemonics = false, importedLength = 0, } = state; + const [, resolveApproval] = useApproval(); const handleNextClick = async (e: React.MouseEvent) => { e?.stopPropagation(); @@ -56,6 +57,12 @@ const ImportSuccess = ({ isPopup = false }: { isPopup?: boolean }) => { return; } + + if (getUiType().isNotification) { + resolveApproval(); + return; + } + history.push('/dashboard'); }; const importedIcon = diff --git a/yarn.lock b/yarn.lock index 47bab9ed016..6616951472d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3612,10 +3612,10 @@ typescript "^4.5.0" web3-core "^1.6.0" -"@rabby-wallet/page-provider@^0.1.23-alpha.2": - version "0.1.23-alpha.2" - resolved "https://registry.yarnpkg.com/@rabby-wallet/page-provider/-/page-provider-0.1.23-alpha.2.tgz#1757a18de9555fe60b2b552f58bc8ec1165fbe00" - integrity sha512-FVXmFxGzjFB4XFQM8Ol/TCaYMivQiuccVjjAOiR5Ukj7gr0ROcUQNSbDKWQ5tQ+1UvkTslxuaKXHFNX23tDjJA== +"@rabby-wallet/page-provider@^0.1.23": + version "0.1.23" + resolved "https://registry.yarnpkg.com/@rabby-wallet/page-provider/-/page-provider-0.1.23.tgz#55f261bbef4bda012bc2c6974aca442681392242" + integrity sha512-K6UeLzsK7kFYiH+YsIkMgjg0IbXTUu6uY2MY3ng0vi2HsVyOGKQTICeynu0/eBt+Mq+WoBIfK7xXDh8J2gyD2g== dependencies: "@ledgerhq/devices" "^6.27.1" "@types/chrome" "^0.0.186"