Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(wallet): Add Loading State for Domain Lookup #16127

Merged
merged 1 commit into from
Nov 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions components/brave_wallet/browser/brave_wallet_constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -942,6 +942,7 @@ constexpr webui::LocalizedString kLocalizedStrings[] = {
{"braveWalletHelpCenter", IDS_BRAVE_WALLET_HELP_CENTER},
{"braveWalletBuyTapBuyNotSupportedMessage",
IDS_BRAVE_WALLET_BUY_TAB_BUY_NOT_SUPPORTED_MESSAGE},
{"braveWalletSearchingForDomain", IDS_BRAVE_WALLET_SEARCHING_FOR_DOMAIN},
{"braveWalletPortfolioTokenDetailsMenuLabel",
IDS_BRAVE_WALLET_PORTFOLIO_TOKEN_DETAILS_MENU_LABEL},
{"braveWalletPortfolioViewOnExplorerMenuLabel",
Expand Down
110 changes: 47 additions & 63 deletions components/brave_wallet_ui/common/hooks/send.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ export default function useSend (isSendTab?: boolean) {
dispatch(SendCryptoActions.setToAddressOrUrl(payload))
}

// State
const [searchingForDomain, setSearchingForDomain] = React.useState<boolean>(false)

const selectSendAsset = (asset: BraveWallet.BlockchainToken | undefined) => {
if (asset?.isErc721 || asset?.isNft) {
setSendAmount('1')
Expand All @@ -102,44 +105,50 @@ export default function useSend (isSendTab?: boolean) {
setAddressError(getLocale('braveWalletNotDomain').replace('$1', url))
}

const handleDomainLookupResponse = React.useCallback((address: string, error: BraveWallet.ProviderError, requireOffchainConsent: boolean) => {
if (address && error === BraveWallet.ProviderError.kSuccess) {
setAddressError('')
setAddressWarning('')
setToAddress(address)
setShowEnsOffchainLookupOptions(requireOffchainConsent)
// If found UD address is the same as the selectedAccounts Wallet Address
if (address.toLowerCase() === selectedAccount?.address?.toLowerCase()) {
setAddressError(getLocale('braveWalletSameAddressError'))
}
setSearchingForDomain(false)
return
}
setShowEnsOffchainLookupOptions(false)
setNotRegisteredError(toAddressOrUrl)
setSearchingForDomain(false)
}, [selectedAccount?.address, toAddressOrUrl])

const handleUDAddressLookUp = React.useCallback(() => {
setSearchingForDomain(true)
setToAddress('')
findUnstoppableDomainAddress(toAddressOrUrl, selectedSendAsset ?? null).then((value: GetUnstoppableDomainsWalletAddrReturnInfo) => {
handleDomainLookupResponse(value.address, value.error, false)
}).catch(e => console.log(e))
}, [findUnstoppableDomainAddress, handleDomainLookupResponse, findSNSAddress, findENSAddress, toAddressOrUrl, selectedSendAsset, selectedAccount?.coin])

const processEthereumAddress = React.useCallback((toAddressOrUrl: string) => {
const valueToLowerCase = toAddressOrUrl.toLowerCase()

// If value ends with a supported ENS extension, will call findENSAddress.
// If success true, will set toAddress else will return error message.
if (endsWithAny(supportedENSExtensions, valueToLowerCase)) {
setSearchingForDomain(true)
setToAddress('')
findENSAddress(toAddressOrUrl, ensOffchainLookupOptions).then((value: GetEthAddrReturnInfo) => {
if (value.error === BraveWallet.ProviderError.kSuccess) {
setAddressError('')
setAddressWarning('')
setToAddress(value.address)
setShowEnsOffchainLookupOptions(value.requireOffchainConsent)
// If found ENS address is the same as the selectedAccounts Wallet Address
if (value.address.toLowerCase() === selectedAccount?.address?.toLowerCase()) {
setAddressError(getLocale('braveWalletSameAddressError'))
}
return
}
setShowEnsOffchainLookupOptions(false)
setNotRegisteredError(valueToLowerCase)
handleDomainLookupResponse(value.address, value.error, value.requireOffchainConsent)
}).catch(e => console.log(e))
return
}

// If value ends with a supported UD extension, will call findUnstoppableDomainAddress.
// If success true, will set toAddress else will return error message.
if (endsWithAny(supportedUDExtensions, valueToLowerCase)) {
findUnstoppableDomainAddress(toAddressOrUrl, selectedSendAsset ?? null).then((value: GetUnstoppableDomainsWalletAddrReturnInfo) => {
if (value.address && value.error === BraveWallet.ProviderError.kSuccess) {
setAddressError('')
setAddressWarning('')
setToAddress(value.address)
// If found UD address is the same as the selectedAccounts Wallet Address
if (value.address.toLowerCase() === selectedAccount?.address?.toLowerCase()) {
setAddressError(getLocale('braveWalletSameAddressError'))
}
return
}
setNotRegisteredError(valueToLowerCase)
}).catch(e => console.log(e))
handleUDAddressLookUp()
return
}

Expand Down Expand Up @@ -198,23 +207,15 @@ export default function useSend (isSendTab?: boolean) {
// Fallback error state
setAddressWarning('')
setAddressError(getLocale('braveWalletNotValidAddress'))
}, [selectedAccount?.address, selectedSendAsset, ensOffchainLookupOptions])
}, [selectedAccount?.address, ensOffchainLookupOptions, handleUDAddressLookUp, handleDomainLookupResponse])

const processFilecoinAddress = React.useCallback((toAddressOrUrl: string) => {
const valueToLowerCase = toAddressOrUrl.toLowerCase()

// If value ends with a supported UD extension, will call findUnstoppableDomainAddress.
// If success true, will set toAddress else will return error message.
if (endsWithAny(supportedUDExtensions, valueToLowerCase)) {
findUnstoppableDomainAddress(toAddressOrUrl, selectedSendAsset ?? null).then((value: GetUnstoppableDomainsWalletAddrReturnInfo) => {
if (value.address && value.error === BraveWallet.ProviderError.kSuccess) {
setAddressError('')
setAddressWarning('')
setToAddress(value.address)
return
}
setNotRegisteredError(valueToLowerCase)
}).catch(e => console.log(e))
handleUDAddressLookUp()
return
}

Expand Down Expand Up @@ -243,43 +244,25 @@ export default function useSend (isSendTab?: boolean) {
// Reset error and warning state back to normal
setAddressWarning('')
setAddressError('')
}, [selectedSendAsset, selectedAccount?.address])
}, [selectedAccount?.address, handleUDAddressLookUp])

const processSolanaAddress = React.useCallback((toAddressOrUrl: string) => {
const valueToLowerCase = toAddressOrUrl.toLowerCase()

// If value ends with a supported UD extension, will call findUnstoppableDomainAddress.
// If success true, will set toAddress else will return error message.
if (endsWithAny(supportedUDExtensions, valueToLowerCase)) {
findUnstoppableDomainAddress(toAddressOrUrl, selectedSendAsset ?? null).then((value: GetUnstoppableDomainsWalletAddrReturnInfo) => {
if (value.address && value.error === BraveWallet.ProviderError.kSuccess) {
setAddressError('')
setAddressWarning('')
setToAddress(value.address)
// If found UD address is the same as the selectedAccounts Wallet Address
if (value.address.toLowerCase() === selectedAccount?.address?.toLowerCase()) {
setAddressError(getLocale('braveWalletSameAddressError'))
}
return
}
setNotRegisteredError(valueToLowerCase)
}).catch(e => console.log(e))
handleUDAddressLookUp()
return
}

// If value ends with a supported SNS extension, will call findENSAddress.
// If success true, will set toAddress else will return error message.
if (endsWithAny(supportedSNSExtensions, valueToLowerCase)) {
setSearchingForDomain(true)
setToAddress('')
findSNSAddress(toAddressOrUrl).then((value: GetSolAddrReturnInfo) => {
if (value.error === BraveWallet.ProviderError.kSuccess) {
setAddressError('')
setAddressWarning('')
setToAddress(value.address)
// If found SNS address is the same as the selectedAccounts Wallet Address
if (value.address.toLowerCase() === selectedAccount?.address?.toLowerCase()) {
setAddressError(getLocale('braveWalletSameAddressError'))
}
return
}
setNotRegisteredError(valueToLowerCase)
handleDomainLookupResponse(value.address, value.error, false)
}).catch(e => console.log(e))
return
}
Expand Down Expand Up @@ -325,7 +308,7 @@ export default function useSend (isSendTab?: boolean) {
setAddressWarning('')
setAddressError('')
})
}, [selectedAccount?.address, selectedSendAsset, fullTokenList])
}, [selectedAccount?.address, fullTokenList, handleUDAddressLookUp, handleDomainLookupResponse])

const resetSendFields = React.useCallback((reselectSendAsset?: boolean) => {
if (isSendTab) {
Expand Down Expand Up @@ -490,6 +473,7 @@ export default function useSend (isSendTab?: boolean) {
sendAmountValidationError,
showEnsOffchainLookupOptions,
ensOffchainLookupOptions,
setEnsOffchainLookupOptions
setEnsOffchainLookupOptions,
searchingForDomain
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

import styled from 'styled-components'

// Assets
import { LoaderIcon } from 'brave-ui/components/icons'

// Shared Styles
import { StyledButton, Icon } from '../../shared.styles'

Expand Down Expand Up @@ -78,3 +81,11 @@ export const ErrorIcon = styled(Icon)`
background-color: ${(p) => p.theme.color.errorBorder};
margin-right: 12px;
`

export const LoadIcon = styled(LoaderIcon)`
color: ${p => p.theme.color.white};
height: 25px;
width: 25px;
opacity: .4;
margin-right: 10px;
`
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import * as React from 'react'
import InfoIcon from '../../../../../assets/svg-icons/info-icon.svg'

// Styled Components
import { Button, ErrorIcon, StandardButtonStyleProps } from './standard-button.style'
import { Button, ErrorIcon, StandardButtonStyleProps, LoadIcon } from './standard-button.style'

interface Props extends StandardButtonStyleProps {
buttonText: string
isLoading: boolean
onClick: () => void
}

Expand All @@ -24,6 +25,7 @@ export const StandardButton = (props: Props) => {
disabled,
marginRight,
hasError,
isLoading,
onClick
} = props

Expand All @@ -39,6 +41,9 @@ export const StandardButton = (props: Props) => {
{hasError &&
<ErrorIcon icon={InfoIcon} size={22} />
}
{isLoading &&
<LoadIcon />
}
{buttonText}
</Button>
)
Expand Down
44 changes: 25 additions & 19 deletions components/brave_wallet_ui/page/screens/send/send/send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ export const Send = (props: Props) => {
setSendAmount,
setToAddressOrUrl,
submitSend,
selectSendAsset
selectSendAsset,
searchingForDomain
} = useSend(true)

// Hooks
Expand Down Expand Up @@ -176,25 +177,28 @@ export const Send = (props: Props) => {
}, [spotPrices, selectedSendAsset, sendAmount, defaultCurrencies.fiat, sendAssetBalance, selectedSendOption])

const reviewButtonText = React.useMemo(() => {
return sendAmountValidationError
? getLocale('braveWalletDecimalPlacesError')
: insufficientFundsError
? getLocale('braveWalletNotEnoughFunds')
: (addressError !== undefined && addressError !== '')
? addressError
: (addressWarning !== undefined && addressWarning !== '')
? addressWarning
: getLocale('braveWalletReviewOrder')
}, [insufficientFundsError, addressError, addressWarning, sendAmountValidationError])
return searchingForDomain
? getLocale('braveWalletSearchingForDomain')
: sendAmountValidationError
? getLocale('braveWalletDecimalPlacesError')
: insufficientFundsError
? getLocale('braveWalletNotEnoughFunds')
: (addressError !== undefined && addressError !== '')
? addressError
: (addressWarning !== undefined && addressWarning !== '')
? addressWarning
: getLocale('braveWalletReviewOrder')
}, [insufficientFundsError, addressError, addressWarning, sendAmountValidationError, searchingForDomain])

const isReviewButtonDisabled = React.useMemo(() => {
return toAddressOrUrl === '' ||
return searchingForDomain ||
toAddressOrUrl === '' ||
parseFloat(sendAmount) === 0 ||
sendAmount === '' ||
insufficientFundsError ||
(addressError !== undefined && addressError !== '') ||
sendAmountValidationError !== undefined
}, [toAddressOrUrl, sendAmount, insufficientFundsError, addressError, sendAmountValidationError])
}, [toAddressOrUrl, sendAmount, insufficientFundsError, addressError, sendAmountValidationError, searchingForDomain])

const selectedTokensNetwork = React.useMemo(() => {
if (selectedSendAsset) {
Expand Down Expand Up @@ -347,8 +351,9 @@ export const Send = (props: Props) => {
<DIVForWidth id={INPUT_WIDTH_ID}>{toAddressOrUrl}</DIVForWidth>
<AddressInput
placeholder={getLocale('braveWalletEnterRecipientAddress')}
hasError={
(addressError !== undefined && addressError !== '') ||
hasError={searchingForDomain
? false
: (addressError !== undefined && addressError !== '') ||
(addressWarning !== undefined && addressWarning !== '')
}
value={toAddressOrUrl}
Expand All @@ -362,11 +367,12 @@ export const Send = (props: Props) => {
onClick={submitSend}
buttonType='primary'
buttonWidth='full'
isLoading={searchingForDomain}
disabled={isReviewButtonDisabled}
hasError={
insufficientFundsError ||
(addressError !== undefined && addressError !== '')
}
hasError={searchingForDomain
? false
: insufficientFundsError ||
(addressError !== undefined && addressError !== '')}
/>
</SendContainer>
<Background
Expand Down
1 change: 1 addition & 0 deletions components/brave_wallet_ui/stories/locale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ provideStrings({
braveWalletSwapFeesNotice: 'Quote includes a $1 Brave fee.',
braveWalletDecimalPlacesError: 'Too many decimal places',
braveWalletBuyTapBuyNotSupportedMessage: 'Buy not supported for selected network',
braveWalletSearchingForDomain: 'Searching for domain...',

// Send Tab
braveWalletSendToken: 'Send token',
Expand Down
1 change: 1 addition & 0 deletions components/resources/wallet_strings.grdp
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
<message name="IDS_BRAVE_WALLET_SEARCH_NFTS" desc="Send tab search for nfts.">Search NFT by name, id</message>
<message name="IDS_BRAVE_WALLET_BUY_NOT_SUPPORTED_TOOLTIP" desc="Tooltip text when buy action is not supported">Buy support is not available for <ph name="NETWORK"><ex>Binance Smart Chain</ex>$1</ph></message>
<message name="IDS_BRAVE_WALLET_BUY_TAB_BUY_NOT_SUPPORTED_MESSAGE" desc="Message shown when the selected network is not supported for buy transactions">Buy not supported for selected network</message>
<message name="IDS_BRAVE_WALLET_SEARCHING_FOR_DOMAIN" desc="Message shown when searching for a UD or ENS domain">Searching for domain...</message>
<message name="IDS_BRAVE_WALLET_SWAP_NOT_SUPPORTED_TOOLTIP" desc="Tooltip text when swap action is not supported">Swap support is not available for <ph name="NETWORK"><ex>Binance Smart Chain</ex>$1</ph></message>
<message name="IDS_BRAVE_WALLET_SLIPPAGE_TOLERANCE_WARNING" desc="Warning if slippage tolerance is to high">Transaction may be frontrun</message>
<message name="IDS_BRAVE_WALLET_SLIPPAGE_TOLERANCE_TITLE" desc="BuySendSwapo slippage tolerance title">Slippage tolerance</message>
Expand Down