Skip to content

Commit

Permalink
rename on watch wallet (#1338)
Browse files Browse the repository at this point in the history
Co-authored-by: Daniel Sinclair <[email protected]>
  • Loading branch information
greg-schrammel and DanielSinclair authored Feb 20, 2024
1 parent 44a111e commit a0a1baf
Showing 1 changed file with 173 additions and 143 deletions.
316 changes: 173 additions & 143 deletions src/entries/popup/components/WatchWallet/WatchWallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import { isAddress } from '@ethersproject/address';
import { Address } from '@wagmi/core';
import { motion } from 'framer-motion';
import { ChangeEvent, useCallback, useMemo, useReducer, useState } from 'react';
import { useEnsAddress } from 'wagmi';
import { useEnsAddress, useEnsName } from 'wagmi';

import { i18n } from '~/core/languages';
import { useCurrentAddressStore } from '~/core/state';
import { useSavedEnsNames } from '~/core/state/savedEnsNames';
import { ChainId } from '~/core/types/chains';
import { isENSAddressFormat } from '~/core/utils/ethereum';
import {
Box,
Expand All @@ -32,6 +33,7 @@ import {
import * as wallet from '../../handlers/wallet';
import { useDebounce } from '../../hooks/useDebounce';
import { AddressAndType, useWallets } from '../../hooks/useWallets';
import { RenameWalletPrompt } from '../../pages/walletSwitcher/renameWalletPrompt';
import { AddressOrEns } from '../AddressOrEns/AddressorEns';
import { Checkbox } from '../Checkbox/Checkbox';
import { Spinner } from '../Spinner/Spinner';
Expand Down Expand Up @@ -197,9 +199,12 @@ const getError = (
};

export const useValidateInput = (input: string) => {
const isInputEns = isENSAddressFormat(input);

const { data: addressFromEns, isFetching: isFetchingEns } = useEnsAddress({
name: input,
enabled: isENSAddressFormat(input),
enabled: isInputEns,
chainId: ChainId.mainnet,
});
const { savedNames } = useSavedEnsNames();

Expand All @@ -221,6 +226,7 @@ export const useValidateInput = (input: string) => {

return {
ensName: !!addressFromEns && input,
isInputEns,
address,
isLoading,
isValid,
Expand Down Expand Up @@ -249,18 +255,30 @@ export const WatchWallet = ({
isLoading,
isValid: inputIsValid,
error,
isInputEns,
} = useValidateInput(input.trim());

const addressesToImport = useMemo(
() => [address, ...Object.keys(selectedAddresses)].filter(Boolean),
[address, selectedAddresses],
);

const isValid = input ? inputIsValid : !!addressesToImport.length;

const { setCurrentAddress } = useCurrentAddressStore();
const { save } = useSavedEnsNames();

const [renameAccount, setRenameAccount] = useState<Address>();
const { data: ensFromAddress, isFetching: isFetchingAddressEns } = useEnsName(
{
address,
enabled: !isInputEns && !!address,
chainId: ChainId.mainnet,
},
);

const isValid = input
? inputIsValid && !isFetchingAddressEns
: !!addressesToImport.length;

const handleWatchWallet = useCallback(async () => {
const importedAddresses = await Promise.all(
addressesToImport.map(wallet.importWithSecret),
Expand All @@ -273,163 +291,175 @@ export const WatchWallet = ({
save(ensName, address);
}
setCurrentAddress(importedAddresses[0]);
onFinishImporting?.();
if (!onboarding && !ensName && !ensFromAddress) setRenameAccount(address);
else onFinishImporting?.();
}
}, [
addressesToImport,
ensName,
ensFromAddress,
address,
setCurrentAddress,
onboarding,
onFinishImporting,
save,
]);

return (
<Rows alignVertical="justify">
<Row height="content">
<Stack space="24px" alignHorizontal="center">
<Stack space="12px">
<Text size="16pt" weight="bold" color="label" align="center">
{i18n.t('watch_wallet.title')}
</Text>
<Box paddingHorizontal="14px">
<Text
size="12pt"
weight="regular"
color="labelTertiary"
align="center"
>
{i18n.t('watch_wallet.description')}
<>
<RenameWalletPrompt
account={renameAccount}
onClose={() => {
setRenameAccount(undefined);
onFinishImporting?.();
}}
/>
<Rows alignVertical="justify">
<Row height="content">
<Stack space="24px" alignHorizontal="center">
<Stack space="12px">
<Text size="16pt" weight="bold" color="label" align="center">
{i18n.t('watch_wallet.title')}
</Text>
</Box>
</Stack>
<Box paddingHorizontal="14px">
<Text
size="12pt"
weight="regular"
color="labelTertiary"
align="center"
>
{i18n.t('watch_wallet.description')}
</Text>
</Box>
</Stack>

<Box alignItems="center" width="full" style={{ width: '106px' }}>
<Separator color="separatorTertiary" strokeWeight="1px" />
</Box>
<Box alignItems="center" width="full" style={{ width: '106px' }}>
<Separator color="separatorTertiary" strokeWeight="1px" />
</Box>

<Box width="full">
<Stack space="24px" alignHorizontal="center">
<Box width="full">
<Stack space="10px">
<Box
as={motion.div}
whileTap={{ scale: transformScales['0.96'] }}
transition={transitions.bounce}
height="full"
width="full"
key={`address_1`}
position="relative"
>
<Box width="full">
<Stack space="24px" alignHorizontal="center">
<Box width="full">
<Stack space="10px">
<Box
as="textarea"
testId="secret-text-area-watch"
background="surfaceSecondaryElevated"
borderRadius="12px"
borderWidth="1px"
borderColor={{
focus: error ? 'orange' : 'accent',
default: 'buttonStroke',
}}
as={motion.div}
whileTap={{ scale: transformScales['0.96'] }}
transition={transitions.bounce}
height="full"
width="full"
padding="12px"
placeholder={i18n.t('watch_wallet.placeholder')}
value={input}
onKeyDown={(e) => {
if (isValid && e.key === 'Enter') handleWatchWallet();
}}
tabIndex={1}
autoFocus
spellCheck={false}
onChange={onInputChange}
className={[
placeholderStyle,
textStyles({
color: 'label',
fontSize: '14pt',
fontWeight: 'regular',
fontFamily: 'rounded',
}),
]}
style={{
caretColor: accentColorAsHsl,
transition: 'border-color 200ms',
height: '96px',
resize: 'none',
}}
/>
<Box
position="absolute"
marginTop="-24px"
paddingLeft="12px"
key={`address_1`}
position="relative"
>
{isLoading && (
<Box
width="fit"
alignItems="center"
justifyContent="center"
>
<Spinner size={11} color="labelTertiary" />
</Box>
)}
{error && (
<Inline space="4px" alignVertical="center">
<Symbol
symbol={error.symbol}
size={11}
color={'orange'}
weight={'bold'}
/>
<Text size="11pt" weight="regular" color={'orange'}>
{error.message}
</Text>
</Inline>
)}
<Box
as="textarea"
testId="secret-text-area-watch"
background="surfaceSecondaryElevated"
borderRadius="12px"
borderWidth="1px"
borderColor={{
focus: error ? 'orange' : 'accent',
default: 'buttonStroke',
}}
width="full"
padding="12px"
placeholder={i18n.t('watch_wallet.placeholder')}
value={input}
onKeyDown={(e) => {
if (isValid && e.key === 'Enter') handleWatchWallet();
}}
tabIndex={1}
autoFocus
spellCheck={false}
onChange={onInputChange}
className={[
placeholderStyle,
textStyles({
color: 'label',
fontSize: '14pt',
fontWeight: 'regular',
fontFamily: 'rounded',
}),
]}
style={{
caretColor: accentColorAsHsl,
transition: 'border-color 200ms',
height: '96px',
resize: 'none',
}}
/>
<Box
position="absolute"
marginTop="-24px"
paddingLeft="12px"
>
{(isLoading || isFetchingAddressEns) && (
<Box
width="fit"
alignItems="center"
justifyContent="center"
>
<Spinner size={11} color="labelTertiary" />
</Box>
)}
{error && (
<Inline space="4px" alignVertical="center">
<Symbol
symbol={error.symbol}
size={11}
color={'orange'}
weight={'bold'}
/>
<Text size="11pt" weight="regular" color={'orange'}>
{error.message}
</Text>
</Inline>
)}
</Box>
</Box>
</Box>
</Stack>
</Box>
</Stack>
</Stack>
</Box>
</Stack>
</Box>
{onboarding && (
<>
<Box width="full" style={{ width: '106px' }}>
<Separator color="separatorTertiary" strokeWeight="1px" />
</Box>
<RecommendedWatchWallets
selected={selectedAddresses}
onToggle={(address) =>
setSelectedAddresses((all) => {
if (all[address]) delete all[address];
else all[address] = true;
return { ...all };
})
}
/>
</>
)}
</Stack>
</Row>
<Row height="content">
<Box width="full" paddingVertical="20px">
<Button
symbol="eyes.inverse"
symbolSide="left"
height="44px"
color={isValid ? 'accent' : 'labelQuaternary'}
variant={isValid ? 'flat' : 'disabled'}
disabled={!isValid}
width="full"
onClick={handleWatchWallet}
testId={`watch-wallets-button${isValid ? '-ready' : ''}`}
tabIndex={onboarding ? 0 : 2}
>
{addressesToImport.length > 1
? i18n.t('watch_wallet.watch_wallets')
: i18n.t('watch_wallet.watch_wallet')}
</Button>
</Box>
{onboarding && (
<>
<Box width="full" style={{ width: '106px' }}>
<Separator color="separatorTertiary" strokeWeight="1px" />
</Box>
<RecommendedWatchWallets
selected={selectedAddresses}
onToggle={(address) =>
setSelectedAddresses((all) => {
if (all[address]) delete all[address];
else all[address] = true;
return { ...all };
})
}
/>
</>
)}
</Stack>
</Row>
<Row height="content">
<Box width="full" paddingVertical="20px">
<Button
symbol="eyes.inverse"
symbolSide="left"
height="44px"
color={isValid ? 'accent' : 'labelQuaternary'}
variant={isValid ? 'flat' : 'disabled'}
disabled={!isValid}
width="full"
onClick={handleWatchWallet}
testId={`watch-wallets-button${isValid ? '-ready' : ''}`}
tabIndex={onboarding ? 0 : 2}
>
{addressesToImport.length > 1
? i18n.t('watch_wallet.watch_wallets')
: i18n.t('watch_wallet.watch_wallet')}
</Button>
</Box>
</Row>
</Rows>
</Row>
</Rows>
</>
);
};

0 comments on commit a0a1baf

Please sign in to comment.