mirror of
https://github.com/RabbyHub/Rabby.git
synced 2026-04-17 03:01:32 -04:00
feat: simplified sign page footerbar ui (#2564)
* feat: simplified sign page ui * wip * fix: footbar * fix: ui bugs * feat: ledger unlock
This commit is contained in:
@@ -37,7 +37,7 @@
|
||||
"gasLimitLessThanGasUsed": "Gas limit is too low. There is 95% chance that the transaction may fail.",
|
||||
"nativeTokenNotEngouthForGas": "Gas balance is not enough for transaction",
|
||||
"nonceLowerThanExpect": "Nonce is too low, the minimum should be {{0}}",
|
||||
"canOnlyUseImportedAddress": "You can only use imported addresses to sign",
|
||||
"canOnlyUseImportedAddress": "You cannot sign transactions with a watch-only address.",
|
||||
"multiSigChainNotMatch": "Multi-signature addresses are not on this chain and cannot initiate transactions",
|
||||
"safeAddressNotSupportChain": "Current safe address is not supported on {{0}} chain",
|
||||
"noGasRequired": "No gas required",
|
||||
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
FeeMarketEIP1559Transaction,
|
||||
} from '@ethereumjs/tx';
|
||||
import { EVENTS } from 'consts';
|
||||
import { isSameAddress, wait } from '@/background/utils';
|
||||
import { isSameAddress } from '@/background/utils';
|
||||
import { SignHelper, LedgerHDPathType } from './helper';
|
||||
|
||||
const type = 'Ledger Hardware';
|
||||
@@ -303,11 +303,10 @@ class LedgerBridgeKeyring {
|
||||
// wait connect the WebHID
|
||||
while (!this.app) {
|
||||
await this.makeApp();
|
||||
await wait(() => {
|
||||
if (count++ > 50) {
|
||||
throw new Error('Ledger: Failed to connect to Ledger');
|
||||
}
|
||||
}, 100);
|
||||
await new Promise((resolve) => setTimeout(resolve, 100));
|
||||
if (count++ > 50) {
|
||||
throw new Error('Ledger: Failed to connect to Ledger');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -57,15 +57,6 @@ export function normalizeAddress(input: number | string): string {
|
||||
return ethUtil.addHexPrefix(input);
|
||||
}
|
||||
|
||||
export const wait = (fn: () => void, ms = 1000) => {
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
fn();
|
||||
resolve(true);
|
||||
}, ms);
|
||||
});
|
||||
};
|
||||
|
||||
export const setPageStateCacheWhenPopupClose = (data) => {
|
||||
const cache = pageStateCache.get();
|
||||
if (cache && cache.path === '/import/wallet-connect') {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { Tooltip } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import { KEYRING_ICONS, WALLET_BRAND_CONTENT } from 'consts';
|
||||
import React, {
|
||||
memo,
|
||||
MouseEventHandler,
|
||||
@@ -15,12 +14,10 @@ import { useRabbySelector } from '@/ui/store';
|
||||
|
||||
import { ReactComponent as RcIconWhitelist } from 'ui/assets/address/whitelist.svg';
|
||||
import { CopyChecked } from '@/ui/component/CopyChecked';
|
||||
import { useWalletConnectIcon } from '@/ui/component/WalletConnect/useWalletConnectIcon';
|
||||
import { CommonSignal } from '@/ui/component/ConnectStatus/CommonSignal';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import ThemeIcon from '../ThemeMode/ThemeIcon';
|
||||
import { pickKeyringThemeIcon } from '@/utils/account';
|
||||
import { useThemeMode } from '@/ui/hooks/usePreference';
|
||||
import { useBrandIcon } from '@/ui/hooks/useBrandIcon';
|
||||
|
||||
export interface AddressItemProps {
|
||||
balance: number;
|
||||
@@ -60,24 +57,12 @@ const AddressItem = memo(
|
||||
const alias = _alias || aliasName;
|
||||
const titleRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const brandIcon = useWalletConnectIcon({
|
||||
const addressTypeIcon = useBrandIcon({
|
||||
address,
|
||||
brandName,
|
||||
type,
|
||||
});
|
||||
|
||||
const { isDarkTheme } = useThemeMode();
|
||||
|
||||
const addressTypeIcon = useMemo(
|
||||
() =>
|
||||
brandIcon ||
|
||||
pickKeyringThemeIcon(type as any, isDarkTheme) ||
|
||||
KEYRING_ICONS[type] ||
|
||||
pickKeyringThemeIcon(brandName as any, isDarkTheme) ||
|
||||
WALLET_BRAND_CONTENT?.[brandName]?.image,
|
||||
[type, brandName, brandIcon, isDarkTheme]
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
|
||||
49
src/ui/hooks/useBrandIcon.ts
Normal file
49
src/ui/hooks/useBrandIcon.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { useWalletConnectIcon } from '../component/WalletConnect/useWalletConnectIcon';
|
||||
import { useThemeMode } from './usePreference';
|
||||
import React from 'react';
|
||||
import { pickKeyringThemeIcon } from '@/utils/account';
|
||||
import {
|
||||
KEYRING_ICONS,
|
||||
KEYRINGS_LOGOS,
|
||||
WALLET_BRAND_CONTENT,
|
||||
} from '@/constant';
|
||||
|
||||
export const useBrandIcon = ({
|
||||
address,
|
||||
brandName,
|
||||
type,
|
||||
forceLight,
|
||||
}: {
|
||||
address: string;
|
||||
brandName: string;
|
||||
type: string;
|
||||
forceLight?: boolean;
|
||||
}) => {
|
||||
const brandIcon = useWalletConnectIcon({
|
||||
address,
|
||||
brandName,
|
||||
type,
|
||||
});
|
||||
|
||||
const { isDarkTheme } = useThemeMode();
|
||||
|
||||
const addressTypeIcon = React.useMemo(
|
||||
() =>
|
||||
forceLight
|
||||
? brandIcon ||
|
||||
pickKeyringThemeIcon(type as any, {
|
||||
needLightVersion: true,
|
||||
}) ||
|
||||
WALLET_BRAND_CONTENT?.[brandName]?.image ||
|
||||
KEYRINGS_LOGOS[type]
|
||||
: brandIcon ||
|
||||
pickKeyringThemeIcon(brandName as any, {
|
||||
needLightVersion: isDarkTheme,
|
||||
}) ||
|
||||
WALLET_BRAND_CONTENT?.[brandName]?.image ||
|
||||
KEYRING_ICONS[type],
|
||||
[type, brandName, brandIcon, isDarkTheme]
|
||||
);
|
||||
|
||||
return addressTypeIcon;
|
||||
};
|
||||
@@ -3,12 +3,12 @@ import { useEffect, useRef, useState, useCallback } from 'react';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Approval } from 'background/service/notification';
|
||||
import { useWallet } from './WalletContext';
|
||||
import { getUiType } from './index';
|
||||
import { KEYRING_TYPE_TEXT, WALLET_BRAND_CONTENT } from '@/constant';
|
||||
import { LedgerHDPathType, LedgerHDPathTypeLabel } from '@/ui/utils/ledger';
|
||||
import { useApprovalPopup } from './approval-popup';
|
||||
import { useRabbyDispatch, useRabbySelector } from '../store';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useDeviceConnect } from './useDeviceConnect';
|
||||
|
||||
export const useApproval = () => {
|
||||
const wallet = useWallet();
|
||||
@@ -16,6 +16,7 @@ export const useApproval = () => {
|
||||
const { showPopup, enablePopup } = useApprovalPopup();
|
||||
|
||||
const getApproval: () => Promise<Approval> = wallet.getApproval;
|
||||
const deviceConnect = useDeviceConnect();
|
||||
|
||||
const resolveApproval = async (
|
||||
data?: any,
|
||||
@@ -23,6 +24,11 @@ export const useApproval = () => {
|
||||
forceReject = false,
|
||||
approvalId?: string
|
||||
) => {
|
||||
// handle connect
|
||||
if (!(await deviceConnect(data.type))) {
|
||||
return;
|
||||
}
|
||||
|
||||
const approval = await getApproval();
|
||||
|
||||
if (approval) {
|
||||
|
||||
76
src/ui/utils/useDeviceConnect.ts
Normal file
76
src/ui/utils/useDeviceConnect.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { KEYRING_CLASS } from '@/constant';
|
||||
import React from 'react';
|
||||
import { useLedgerStatus } from '../component/ConnectStatus/useLedgerStatus';
|
||||
import { useCommonPopupView, useWallet } from './WalletContext';
|
||||
import { useSessionStatus } from '../component/WalletConnect/useSessionStatus';
|
||||
import { useCurrentAccount } from '../hooks/backgroundState/useAccount';
|
||||
import { useImKeyStatus } from '../component/ConnectStatus/useImKeyStatus';
|
||||
|
||||
/**
|
||||
* some devices require a connection to the device to sign transactions
|
||||
* ledger, walletConnect, gridplus, etc
|
||||
*/
|
||||
export const useDeviceConnect = () => {
|
||||
const ledgerStatus = useLedgerStatus();
|
||||
const account = useCurrentAccount();
|
||||
const walletConnectStatus = useSessionStatus(account!);
|
||||
const imKeyStatus = useImKeyStatus();
|
||||
const { activePopup, setAccount } = useCommonPopupView();
|
||||
const wallet = useWallet();
|
||||
|
||||
/**
|
||||
* @returns {boolean} true if connected, false if not connected and popup is shown
|
||||
*/
|
||||
const connect = React.useCallback(
|
||||
async (type: string) => {
|
||||
if (type === KEYRING_CLASS.HARDWARE.LEDGER) {
|
||||
if (ledgerStatus.status === 'DISCONNECTED') {
|
||||
activePopup('Ledger');
|
||||
return false;
|
||||
} else {
|
||||
try {
|
||||
await wallet.requestKeyring(
|
||||
KEYRING_CLASS.HARDWARE.LEDGER,
|
||||
'cleanUp',
|
||||
null
|
||||
);
|
||||
await wallet.requestKeyring(
|
||||
KEYRING_CLASS.HARDWARE.LEDGER,
|
||||
'unlock',
|
||||
null,
|
||||
"m/44'/60'/0'/0"
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
activePopup('Ledger');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else if (type === KEYRING_CLASS.WALLETCONNECT) {
|
||||
if (
|
||||
!walletConnectStatus.status ||
|
||||
walletConnectStatus.status === 'DISCONNECTED'
|
||||
) {
|
||||
if (account) {
|
||||
setAccount({
|
||||
...account,
|
||||
type,
|
||||
});
|
||||
}
|
||||
activePopup('WalletConnect');
|
||||
return false;
|
||||
}
|
||||
} else if (type === KEYRING_CLASS.HARDWARE.IMKEY) {
|
||||
if (imKeyStatus.status === 'DISCONNECTED') {
|
||||
activePopup('ImKeyPermission');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
[ledgerStatus, walletConnectStatus, imKeyStatus, account]
|
||||
);
|
||||
|
||||
return connect;
|
||||
};
|
||||
@@ -2,11 +2,8 @@ import { message, Tooltip } from 'antd';
|
||||
import clsx from 'clsx';
|
||||
import {
|
||||
BRAND_ALIAN_TYPE_TEXT,
|
||||
KEYRINGS_LOGOS,
|
||||
KEYRING_CLASS,
|
||||
KEYRING_ICONS,
|
||||
KEYRING_TYPE_TEXT,
|
||||
KeyringWithIcon,
|
||||
WALLET_BRAND_CONTENT,
|
||||
} from 'consts';
|
||||
import React, {
|
||||
@@ -31,11 +28,9 @@ import IconCheck from 'ui/assets/check.svg';
|
||||
import { ReactComponent as RcIconWhitelist } from 'ui/assets/address/whitelist.svg';
|
||||
import { CopyChecked } from '@/ui/component/CopyChecked';
|
||||
import SkeletonInput from 'antd/lib/skeleton/Input';
|
||||
import { useWalletConnectIcon } from '@/ui/component/WalletConnect/useWalletConnectIcon';
|
||||
import { CommonSignal } from '@/ui/component/ConnectStatus/CommonSignal';
|
||||
import { pickKeyringThemeIcon } from '@/utils/account';
|
||||
import { useThemeMode } from '@/ui/hooks/usePreference';
|
||||
import ThemeIcon from '@/ui/component/ThemeMode/ThemeIcon';
|
||||
import { useBrandIcon } from '@/ui/hooks/useBrandIcon';
|
||||
|
||||
export interface AddressItemProps {
|
||||
balance: number;
|
||||
@@ -149,32 +144,13 @@ const AddressItem = memo(
|
||||
};
|
||||
}, []);
|
||||
|
||||
const brandIcon = useWalletConnectIcon({
|
||||
const addressTypeIcon = useBrandIcon({
|
||||
address,
|
||||
brandName,
|
||||
type,
|
||||
forceLight: isCurrentAccount,
|
||||
});
|
||||
|
||||
const { isDarkTheme } = useThemeMode();
|
||||
|
||||
const addressTypeIcon = useMemo(
|
||||
() =>
|
||||
isCurrentAccount
|
||||
? brandIcon ||
|
||||
pickKeyringThemeIcon(type as any, {
|
||||
needLightVersion: true,
|
||||
}) ||
|
||||
WALLET_BRAND_CONTENT?.[brandName]?.image ||
|
||||
KEYRINGS_LOGOS[type]
|
||||
: brandIcon ||
|
||||
pickKeyringThemeIcon(brandName as any, {
|
||||
needLightVersion: isDarkTheme,
|
||||
}) ||
|
||||
WALLET_BRAND_CONTENT?.[brandName]?.image ||
|
||||
KEYRING_ICONS[type],
|
||||
[type, brandName, brandIcon, isDarkTheme]
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={clsx(className, 'rabby-address-item-container relative')}>
|
||||
{canFastDeleteAccount && (
|
||||
|
||||
@@ -1,26 +1,14 @@
|
||||
import { Account } from '@/background/service/preference';
|
||||
import {
|
||||
KEYRING_ICONS,
|
||||
KEYRING_CLASS,
|
||||
WALLET_BRAND_CONTENT,
|
||||
WALLET_BRAND_TYPES,
|
||||
KEYRING_ICONS_WHITE,
|
||||
} from '@/constant';
|
||||
import { KEYRING_CLASS } from '@/constant';
|
||||
import { AddressViewer } from '@/ui/component';
|
||||
import useCurrentBalance from '@/ui/hooks/useCurrentBalance';
|
||||
import { splitNumberByStep, useWallet } from '@/ui/utils';
|
||||
import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { WalletConnectAccount } from './WalletConnectAccount';
|
||||
import { Chain } from '@debank/common';
|
||||
import { LedgerAccount } from './LedgerAccount';
|
||||
import { CommonAccount } from './CommonAccount';
|
||||
import { KeystoneAccount } from './KeystoneAccount';
|
||||
import { GridPlusAccount } from './GridPlusAccount';
|
||||
import { Tooltip } from 'antd';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useThemeMode } from '@/ui/hooks/usePreference';
|
||||
import { ImKeyAccount } from './ImKeyAccount';
|
||||
import { useBrandIcon } from '@/ui/hooks/useBrandIcon';
|
||||
|
||||
export interface Props {
|
||||
account: Account;
|
||||
@@ -62,26 +50,47 @@ export const AccountInfo: React.FC<Props> = ({
|
||||
init();
|
||||
}, [account]);
|
||||
|
||||
const { isDarkTheme } = useThemeMode();
|
||||
const brandIcon = useBrandIcon({
|
||||
address: account?.address,
|
||||
brandName: account?.brandName,
|
||||
type: account?.type,
|
||||
});
|
||||
|
||||
const nicknameRef = React.useRef<HTMLDivElement>(null);
|
||||
const [enableTooltip, setEnableTooltip] = React.useState(false);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (nicknameRef.current) {
|
||||
setEnableTooltip(
|
||||
nicknameRef.current.offsetWidth < nicknameRef.current.scrollWidth
|
||||
);
|
||||
}
|
||||
}, [nickname]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
'bg-r-neutral-card-3 rounded-[8px]',
|
||||
'py-[12px] px-[16px] mb-[12px]',
|
||||
'py-[12px] px-[12px] mb-[12px]',
|
||||
'space-y-6'
|
||||
)}
|
||||
>
|
||||
<div className={clsx('flex items-center justify-between', 'h-18')}>
|
||||
<div className="space-x-6 flex items-center">
|
||||
<div
|
||||
className={clsx('flex items-center justify-between', 'h-18 gap-x-16')}
|
||||
>
|
||||
<div className="space-x-6 flex items-center overflow-hidden">
|
||||
<img src={brandIcon} className="w-18 h-18" />
|
||||
|
||||
<Tooltip
|
||||
overlayClassName="rectangle w-[max-content]"
|
||||
title={nickname}
|
||||
trigger={enableTooltip ? 'hover' : ''}
|
||||
>
|
||||
<div
|
||||
ref={nicknameRef}
|
||||
className={clsx(
|
||||
'text-r-neutral-body text-[15px]',
|
||||
'max-w-[170px] overflow-ellipsis whitespace-nowrap overflow-hidden',
|
||||
'overflow-ellipsis whitespace-nowrap overflow-hidden',
|
||||
'leading-[20px]'
|
||||
)}
|
||||
>
|
||||
@@ -94,6 +103,7 @@ export const AccountInfo: React.FC<Props> = ({
|
||||
className={clsx('text-13 text-r-neutral-foot')}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{isTestnet ? null : (
|
||||
<div
|
||||
className="text-13 font-normal text-r-neutral-foot"
|
||||
@@ -103,134 +113,6 @@ export const AccountInfo: React.FC<Props> = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{account?.type === KEYRING_CLASS.WALLETCONNECT && (
|
||||
<WalletConnectAccount chain={chain} account={account} />
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.HARDWARE.LEDGER && <LedgerAccount />}
|
||||
{account?.type === KEYRING_CLASS.HARDWARE.IMKEY && <ImKeyAccount />}
|
||||
{account?.type === KEYRING_CLASS.HARDWARE.GRIDPLUS && <GridPlusAccount />}
|
||||
{account?.type === KEYRING_CLASS.HARDWARE.ONEKEY && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.ONEKEY.lightIcon
|
||||
: WALLET_BRAND_CONTENT.ONEKEY.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.onekey')}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.HARDWARE.TREZOR && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.TREZOR.lightIcon
|
||||
: WALLET_BRAND_CONTENT.TREZOR.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.trezor')}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.HARDWARE.BITBOX02 && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.BITBOX02.lightIcon
|
||||
: WALLET_BRAND_CONTENT.BITBOX02.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.bitbox')}
|
||||
/>
|
||||
)}
|
||||
{account?.brandName === WALLET_BRAND_TYPES.KEYSTONE && (
|
||||
<KeystoneAccount />
|
||||
)}
|
||||
{account?.brandName === WALLET_BRAND_TYPES.AIRGAP && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.AirGap.lightIcon
|
||||
: WALLET_BRAND_CONTENT.AirGap.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.airgap')}
|
||||
/>
|
||||
)}
|
||||
{account?.brandName === WALLET_BRAND_TYPES.COOLWALLET && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.CoolWallet.lightIcon
|
||||
: WALLET_BRAND_CONTENT.CoolWallet.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.coolwallet')}
|
||||
/>
|
||||
)}
|
||||
{account?.brandName === WALLET_BRAND_TYPES.IMTOKENOFFLINE && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.imTokenOffline.lightIcon
|
||||
: WALLET_BRAND_CONTENT.imTokenOffline.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.coolwallet')}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.PRIVATE_KEY && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
(isDarkTheme ? KEYRING_ICONS_WHITE : KEYRING_ICONS)[
|
||||
KEYRING_CLASS.PRIVATE_KEY
|
||||
]
|
||||
}
|
||||
grayIcon
|
||||
tip={t('page.signFooterBar.addressTip.privateKey')}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.MNEMONIC && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
(isDarkTheme ? KEYRING_ICONS_WHITE : KEYRING_ICONS)[
|
||||
KEYRING_CLASS.MNEMONIC
|
||||
]
|
||||
}
|
||||
grayIcon
|
||||
tip={
|
||||
needPassphrase
|
||||
? t('page.signFooterBar.addressTip.seedPhraseWithPassphrase')
|
||||
: t('page.signFooterBar.addressTip.seedPhrase')
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.WATCH && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
(isDarkTheme ? KEYRING_ICONS_WHITE : KEYRING_ICONS)[
|
||||
KEYRING_CLASS.WATCH
|
||||
]
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.watchAddress')}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.GNOSIS && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.Gnosis.lightIcon
|
||||
: WALLET_BRAND_CONTENT.Gnosis.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.safe')}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.CoboArgus && (
|
||||
<CommonAccount
|
||||
icon={
|
||||
isDarkTheme
|
||||
? WALLET_BRAND_CONTENT.CoboArgus.lightIcon
|
||||
: WALLET_BRAND_CONTENT.CoboArgus.icon
|
||||
}
|
||||
tip={t('page.signFooterBar.addressTip.coboSafe')}
|
||||
/>
|
||||
)}
|
||||
{account?.type === KEYRING_CLASS.Coinbase && (
|
||||
<WalletConnectAccount chain={chain} account={account} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Props } from './ActionsContainer';
|
||||
import { ProcessActions } from './ProcessActions';
|
||||
import { useGridPlusStatus } from '@/ui/component/ConnectStatus/useGridPlusStatus';
|
||||
|
||||
export const GridPlusProcessActions: React.FC<Props> = (props) => {
|
||||
const { disabledProcess } = props;
|
||||
const { status } = useGridPlusStatus();
|
||||
|
||||
return (
|
||||
<ProcessActions
|
||||
{...props}
|
||||
disabledProcess={status !== 'CONNECTED' || disabledProcess}
|
||||
/>
|
||||
);
|
||||
return <ProcessActions {...props} disabledProcess={disabledProcess} />;
|
||||
};
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Props } from './ActionsContainer';
|
||||
import { ProcessActions } from './ProcessActions';
|
||||
import { useImKeyStatus } from '@/ui/component/ConnectStatus/useImKeyStatus';
|
||||
|
||||
export const ImKeyProcessActions: React.FC<Props> = (props) => {
|
||||
const { disabledProcess } = props;
|
||||
const { status } = useImKeyStatus();
|
||||
|
||||
return (
|
||||
<ProcessActions
|
||||
{...props}
|
||||
disabledProcess={status !== 'CONNECTED' || disabledProcess}
|
||||
/>
|
||||
);
|
||||
return <ProcessActions {...props} disabledProcess={disabledProcess} />;
|
||||
};
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
import React from 'react';
|
||||
import { Props } from './ActionsContainer';
|
||||
import { ProcessActions } from './ProcessActions';
|
||||
import { useLedgerStatus } from '@/ui/component/ConnectStatus/useLedgerStatus';
|
||||
|
||||
export const LedgerProcessActions: React.FC<Props> = (props) => {
|
||||
const { disabledProcess } = props;
|
||||
const { status } = useLedgerStatus();
|
||||
|
||||
return (
|
||||
<ProcessActions
|
||||
{...props}
|
||||
disabledProcess={status !== 'CONNECTED' || disabledProcess}
|
||||
/>
|
||||
);
|
||||
return <ProcessActions {...props} disabledProcess={disabledProcess} />;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button, Tooltip } from 'antd';
|
||||
import { Button } from 'antd';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { ActionsContainer, Props } from './ActionsContainer';
|
||||
@@ -7,6 +7,7 @@ import { ReactComponent as IconClose } from 'ui/assets/close-16-cc.svg';
|
||||
import { GasLessAnimatedWrapper } from './GasLessComponents';
|
||||
import styled from 'styled-components';
|
||||
import { LoadingOutlined } from '@ant-design/icons';
|
||||
import { TooltipWithMagnetArrow } from '@/ui/component/Tooltip/TooltipWithMagnetArrow';
|
||||
|
||||
const ButtonStyled = styled(Button)`
|
||||
&:hover {
|
||||
@@ -86,9 +87,11 @@ export const SubmitActions: React.FC<Props> = ({
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<Tooltip
|
||||
<TooltipWithMagnetArrow
|
||||
overlayClassName="rectangle sign-tx-forbidden-tooltip"
|
||||
title={enableTooltip ? tooltipContent : null}
|
||||
inApproval
|
||||
viewportOffset={[20, -20, -20, 20]}
|
||||
>
|
||||
<GasLessAnimatedWrapper>
|
||||
<ButtonStyled
|
||||
@@ -116,7 +119,7 @@ export const SubmitActions: React.FC<Props> = ({
|
||||
{t('page.signFooterBar.signAndSubmitButton')}
|
||||
</ButtonStyled>
|
||||
</GasLessAnimatedWrapper>
|
||||
</Tooltip>
|
||||
</TooltipWithMagnetArrow>
|
||||
)}
|
||||
</ActionsContainer>
|
||||
);
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
import { Account } from '@/background/service/preference';
|
||||
import {
|
||||
KEYRINGS_LOGOS,
|
||||
WALLET_BRAND_CONTENT,
|
||||
WALLET_BRAND_TYPES,
|
||||
} from '@/constant';
|
||||
import { WALLET_BRAND_TYPES } from '@/constant';
|
||||
import { SessionSignal } from '@/ui/component/WalletConnect/SessionSignal';
|
||||
import { useDisplayBrandName } from '@/ui/component/WalletConnect/useDisplayBrandName';
|
||||
import { useSessionChainId } from '@/ui/component/WalletConnect/useSessionChainId';
|
||||
import { useSessionStatus } from '@/ui/component/WalletConnect/useSessionStatus';
|
||||
import { useWalletConnectIcon } from '@/ui/component/WalletConnect/useWalletConnectIcon';
|
||||
import { useCommonPopupView, useWallet } from '@/ui/utils';
|
||||
import { Chain } from '@debank/common';
|
||||
import { Button } from 'antd';
|
||||
@@ -16,6 +11,7 @@ import clsx from 'clsx';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { CommonAccount } from './CommonAccount';
|
||||
import { useBrandIcon } from '@/ui/hooks/useBrandIcon';
|
||||
|
||||
export interface Props {
|
||||
account: Account;
|
||||
@@ -26,18 +22,12 @@ export const WalletConnectAccount: React.FC<Props> = ({ account, chain }) => {
|
||||
const { activePopup, setAccount, setVisible } = useCommonPopupView();
|
||||
const { t } = useTranslation();
|
||||
const { address, brandName, type } = account;
|
||||
const brandIcon = useWalletConnectIcon({
|
||||
|
||||
const addressTypeIcon = useBrandIcon({
|
||||
address,
|
||||
brandName,
|
||||
type,
|
||||
});
|
||||
const addressTypeIcon = React.useMemo(
|
||||
() =>
|
||||
brandIcon ||
|
||||
WALLET_BRAND_CONTENT?.[brandName]?.image ||
|
||||
KEYRINGS_LOGOS[type],
|
||||
[type, brandName, brandIcon]
|
||||
);
|
||||
const [displayBrandName, realBrandName] = useDisplayBrandName(
|
||||
brandName,
|
||||
address
|
||||
|
||||
@@ -1,54 +1,9 @@
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { Props } from './ActionsContainer';
|
||||
import { useDisplayBrandName } from '@/ui/component/WalletConnect/useDisplayBrandName';
|
||||
import { useSessionChainId } from '@/ui/component/WalletConnect/useSessionChainId';
|
||||
import { useSessionStatus } from '@/ui/component/WalletConnect/useSessionStatus';
|
||||
import { ProcessActions } from './ProcessActions';
|
||||
|
||||
export const WalletConnectProcessActions: React.FC<Props> = (props) => {
|
||||
const {
|
||||
account,
|
||||
disabledProcess,
|
||||
tooltipContent,
|
||||
enableTooltip,
|
||||
chain,
|
||||
} = props;
|
||||
const { t } = useTranslation();
|
||||
const { status } = useSessionStatus(account);
|
||||
const sessionChainId = useSessionChainId(account);
|
||||
const chainError = chain && sessionChainId !== chain.id;
|
||||
const [displayBrandName] = useDisplayBrandName(
|
||||
account.brandName,
|
||||
account.address
|
||||
);
|
||||
const content = React.useMemo(() => {
|
||||
if (status === 'ACCOUNT_ERROR') {
|
||||
return t('page.signFooterBar.walletConnect.wrongAddressAlert');
|
||||
}
|
||||
const { disabledProcess } = props;
|
||||
|
||||
if (!status || status === 'DISCONNECTED') {
|
||||
return t('page.signFooterBar.walletConnect.connectBeforeSign', [
|
||||
displayBrandName,
|
||||
]);
|
||||
}
|
||||
|
||||
// if (chainError) {
|
||||
// return t('page.signFooterBar.walletConnect.chainSwitched', [chain.name]);
|
||||
// }
|
||||
|
||||
return enableTooltip ? tooltipContent : undefined;
|
||||
}, [enableTooltip, tooltipContent, status, chainError, displayBrandName]);
|
||||
|
||||
return (
|
||||
<ProcessActions
|
||||
{...props}
|
||||
tooltipContent={content}
|
||||
disabledProcess={
|
||||
(status !== 'CONNECTED' && status !== 'CHAIN_CHANGED') ||
|
||||
// chainError ||
|
||||
disabledProcess
|
||||
}
|
||||
/>
|
||||
);
|
||||
return <ProcessActions {...props} disabledProcess={disabledProcess} />;
|
||||
};
|
||||
|
||||
@@ -8,10 +8,7 @@ import clsx from 'clsx';
|
||||
import { EVENTS, KEYRING_CLASS } from 'consts';
|
||||
import React, { ReactNode } from 'react';
|
||||
import { ReactComponent as LedgerSVG } from 'ui/assets/walletlogo/ledger.svg';
|
||||
import {
|
||||
ActionGroup,
|
||||
Props as ActionGroupProps,
|
||||
} from '../FooterBar/ActionGroup';
|
||||
import { Props as ActionGroupProps } from '../FooterBar/ActionGroup';
|
||||
import { GasLessConfig } from '../FooterBar/GasLessComponents';
|
||||
import { ProcessActions } from '../FooterBar/ProcessActions';
|
||||
import { Dots } from '../Popup/Dots';
|
||||
|
||||
@@ -218,7 +218,6 @@ export const MiniSignTx = ({
|
||||
const wallet = useWallet();
|
||||
const [support1559, setSupport1559] = useState(chain.eip['1559']);
|
||||
const [isLedger, setIsLedger] = useState(false);
|
||||
const hasConnectedLedgerHID = useLedgerDeviceConnected();
|
||||
const { userData, rules, currentTx, tokenDetail } = useRabbySelector((s) => ({
|
||||
userData: s.securityEngine.userData,
|
||||
rules: s.securityEngine.rules,
|
||||
|
||||
@@ -226,7 +226,6 @@ export const SignTestnetTx = ({ params, origin }: SignTxProps) => {
|
||||
const [nonceChanged, setNonceChanged] = useState(false);
|
||||
const [isReady, setIsReady] = useState(false);
|
||||
const [isLedger, setIsLedger] = useState(false);
|
||||
const hasConnectedLedgerHID = useLedgerDeviceConnected();
|
||||
const [isHardware, setIsHardware] = useState(false);
|
||||
const [nativeTokenBalance, setNativeTokenBalance] = useState('0x0');
|
||||
const [canProcess, setCanProcess] = useState(true);
|
||||
@@ -771,7 +770,6 @@ export const SignTestnetTx = ({ params, origin }: SignTxProps) => {
|
||||
(selectedGas ? selectedGas.price < 0 : true) ||
|
||||
isGnosisAccount ||
|
||||
isCoboArugsAccount ||
|
||||
(isLedger && !hasConnectedLedgerHID) ||
|
||||
!canProcess ||
|
||||
!!checkErrors.find((item) => item.level === 'forbidden')
|
||||
}
|
||||
|
||||
@@ -67,7 +67,6 @@ const SignText = ({ params }: { params: SignTextProps }) => {
|
||||
const [isWatch, setIsWatch] = useState(false);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [isLedger, setIsLedger] = useState(false);
|
||||
const hasConnectedLedgerHID = useLedgerDeviceConnected();
|
||||
const [
|
||||
cantProcessReason,
|
||||
setCantProcessReason,
|
||||
@@ -274,7 +273,7 @@ const SignText = ({ params }: { params: SignTextProps }) => {
|
||||
if (accountType === KEYRING_TYPE.WatchAddressKeyring) {
|
||||
setIsWatch(true);
|
||||
setCantProcessReason(
|
||||
<div>You can only use imported addresses to sign</div>
|
||||
<div>{t('page.signTx.canOnlyUseImportedAddress')}</div>
|
||||
);
|
||||
}
|
||||
if (accountType === KEYRING_TYPE.GnosisKeyring && !params.account) {
|
||||
@@ -450,11 +449,7 @@ const SignText = ({ params }: { params: SignTextProps }) => {
|
||||
tooltipContent={cantProcessReason}
|
||||
onCancel={handleCancel}
|
||||
onSubmit={() => handleAllow()}
|
||||
disabledProcess={
|
||||
(isLedger && !hasConnectedLedgerHID) ||
|
||||
isWatch ||
|
||||
hasUnProcessSecurityResult
|
||||
}
|
||||
disabledProcess={isWatch || hasUnProcessSecurityResult}
|
||||
engineResults={engineResults}
|
||||
onIgnoreAllRules={handleIgnoreAllRules}
|
||||
/>
|
||||
|
||||
@@ -468,7 +468,6 @@ const SignTx = ({ params, origin }: SignTxProps) => {
|
||||
if (!chain) throw new Error('No support chain found');
|
||||
const [support1559, setSupport1559] = useState(chain.eip['1559']);
|
||||
const [isLedger, setIsLedger] = useState(false);
|
||||
const hasConnectedLedgerHID = useLedgerDeviceConnected();
|
||||
const { userData, rules, currentTx, tokenDetail } = useRabbySelector((s) => ({
|
||||
userData: s.securityEngine.userData,
|
||||
rules: s.securityEngine.rules,
|
||||
@@ -2092,7 +2091,6 @@ const SignTx = ({ params, origin }: SignTxProps) => {
|
||||
(selectedGas ? selectedGas.price < 0 : true) ||
|
||||
(isGnosisAccount ? !safeInfo : false) ||
|
||||
(isCoboArugsAccount ? !coboArgusInfo : false) ||
|
||||
(isLedger && !hasConnectedLedgerHID) ||
|
||||
!canProcess ||
|
||||
!!checkErrors.find((item) => item.level === 'forbidden') ||
|
||||
hasUnProcessSecurityResult ||
|
||||
|
||||
@@ -82,7 +82,6 @@ const SignTypedData = ({ params }: { params: SignTypedDataProps }) => {
|
||||
const [footerShowShadow, setFooterShowShadow] = useState(false);
|
||||
const { executeEngine } = useSecurityEngine();
|
||||
const [engineResults, setEngineResults] = useState<Result[]>([]);
|
||||
const hasConnectedLedgerHID = useLedgerDeviceConnected();
|
||||
const dispatch = useRabbyDispatch();
|
||||
const { userData, rules, currentTx, tokenDetail } = useRabbySelector((s) => ({
|
||||
userData: s.securityEngine.userData,
|
||||
@@ -681,12 +680,7 @@ const SignTypedData = ({ params }: { params: SignTypedDataProps }) => {
|
||||
onSubmit={() => handleAllow()}
|
||||
enableTooltip={isWatch}
|
||||
tooltipContent={cantProcessReason}
|
||||
disabledProcess={
|
||||
isLoading ||
|
||||
(isLedger && !hasConnectedLedgerHID) ||
|
||||
isWatch ||
|
||||
hasUnProcessSecurityResult
|
||||
}
|
||||
disabledProcess={isLoading || isWatch || hasUnProcessSecurityResult}
|
||||
isTestnet={chain?.isTestnet}
|
||||
onIgnoreAllRules={handleIgnoreAllRules}
|
||||
/>
|
||||
|
||||
@@ -22,11 +22,12 @@ export const Ledger: React.FC<{
|
||||
}
|
||||
}, [!isModalContent]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!isModalContent && hasConnectedLedgerHID) {
|
||||
closePopup();
|
||||
}
|
||||
}, [hasConnectedLedgerHID, !isModalContent]);
|
||||
// React.useEffect(() => {
|
||||
// if (!isModalContent && hasConnectedLedgerHID && mounted.current) {
|
||||
// closePopup();
|
||||
// }
|
||||
// mounted.current = true;
|
||||
// }, [hasConnectedLedgerHID, !isModalContent]);
|
||||
|
||||
const handleClick = async () => {
|
||||
if (!isModalContent) {
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { AddressViewer, Popup } from '@/ui/component';
|
||||
import { Button } from 'antd';
|
||||
import { PopupProps } from '@/ui/component/Popup';
|
||||
import { useWalletConnectIcon } from '@/ui/component/WalletConnect/useWalletConnectIcon';
|
||||
import { useCurrentAccount } from '@/ui/hooks/backgroundState/useAccount';
|
||||
import { useThemeMode } from '@/ui/hooks/usePreference';
|
||||
import { pickKeyringThemeIcon } from '@/utils/account';
|
||||
import { KEYRING_ICONS, WALLET_BRAND_CONTENT } from '@/constant';
|
||||
import { noop } from 'lodash';
|
||||
import clsx from 'clsx';
|
||||
import { CopyChecked } from '@/ui/component/CopyChecked';
|
||||
@@ -18,6 +14,7 @@ import { ReactComponent as RcIconQuoteStart } from '@/ui/assets/gas-account/quot
|
||||
import { ReactComponent as RcIconQuoteEnd } from '@/ui/assets/gas-account/quote-end.svg';
|
||||
import { GasAccountBlueLogo } from './GasAccountBlueLogo';
|
||||
import { GasAccountWrapperBg } from './WrapperBg';
|
||||
import { useBrandIcon } from '@/ui/hooks/useBrandIcon';
|
||||
|
||||
export const GasACcountCurrentAddress = ({
|
||||
account,
|
||||
@@ -30,30 +27,13 @@ export const GasACcountCurrentAddress = ({
|
||||
}) => {
|
||||
const currentAccount = useCurrentAccount();
|
||||
|
||||
const { isDarkTheme } = useThemeMode();
|
||||
const [alias] = useAlias(account?.address || currentAccount?.address || '');
|
||||
|
||||
const brandIcon = useWalletConnectIcon({
|
||||
const addressTypeIcon = useBrandIcon({
|
||||
address: currentAccount!.address,
|
||||
brandName: currentAccount!.brandName,
|
||||
type: currentAccount!.type,
|
||||
});
|
||||
|
||||
const [alias] = useAlias(account?.address || currentAccount?.address || '');
|
||||
|
||||
const addressTypeIcon = useMemo(
|
||||
() =>
|
||||
brandIcon ||
|
||||
pickKeyringThemeIcon(
|
||||
account?.brandName || (currentAccount!.brandName as any),
|
||||
{
|
||||
needLightVersion: isDarkTheme,
|
||||
}
|
||||
) ||
|
||||
WALLET_BRAND_CONTENT?.[account?.brandName || currentAccount!.brandName]
|
||||
?.image ||
|
||||
KEYRING_ICONS[account?.type || currentAccount!.type],
|
||||
[currentAccount, brandIcon, isDarkTheme]
|
||||
);
|
||||
return (
|
||||
<div className="mb-[20px] py-12 px-16 rounded-[6px] flex items-center bg-r-neutral-card-2">
|
||||
<img src={addressTypeIcon} className="w-24 h-24" />
|
||||
|
||||
Reference in New Issue
Block a user