diff --git a/components/brave_wallet_ui/common/hooks/send.ts b/components/brave_wallet_ui/common/hooks/send.ts index de51d13cc11be..cceb370cb4caf 100644 --- a/components/brave_wallet_ui/common/hooks/send.ts +++ b/components/brave_wallet_ui/common/hooks/send.ts @@ -516,6 +516,7 @@ export default function useSend (isSendTab?: boolean) { setShowEnsOffchainWarning, enableEnsOffchainLookup, searchingForDomain, - processAddressOrUrl + processAddressOrUrl, + sendAssetOptions } } diff --git a/components/brave_wallet_ui/components/desktop/card-headers/nft-asset-header.tsx b/components/brave_wallet_ui/components/desktop/card-headers/nft-asset-header.tsx index d69a8c85269b2..532c8222b13a3 100644 --- a/components/brave_wallet_ui/components/desktop/card-headers/nft-asset-header.tsx +++ b/components/brave_wallet_ui/components/desktop/card-headers/nft-asset-header.tsx @@ -25,11 +25,12 @@ import { Row } from '../../shared/style' interface Props { assetName?: string tokenId?: string + showSendButton: boolean onBack: () => void onSend: () => void } -export const NftAssetHeader = ({ assetName, tokenId, onBack, onSend }: Props) => { +export const NftAssetHeader = ({ assetName, tokenId, showSendButton, onBack, onSend }: Props) => { return ( {assetName} {tokenId ? `#${new Amount(tokenId).toNumber()}` : ''} - {getLocale('braveWalletSend')} + {showSendButton && {getLocale('braveWalletSend')}} ) } diff --git a/components/brave_wallet_ui/components/desktop/views/portfolio/portfolio-asset.tsx b/components/brave_wallet_ui/components/desktop/views/portfolio/portfolio-asset.tsx index 08538e8a1d8ab..37f276e45584b 100644 --- a/components/brave_wallet_ui/components/desktop/views/portfolio/portfolio-asset.tsx +++ b/components/brave_wallet_ui/components/desktop/views/portfolio/portfolio-asset.tsx @@ -440,7 +440,22 @@ export const PortfolioAsset = (props: Props) => { history.push(`${WalletRoutes.DepositFundsPageStart}/${selectedAsset?.symbol}`) }, [selectedAsset?.symbol]) - const onSend = React.useCallback(() => history.push(WalletRoutes.Send), []) + const onSend = React.useCallback(() => { + if (!selectedAsset || !selectedAssetsNetwork) return + + const account = accounts + .filter((account) => account.coin === selectedAsset.coin) + .find(acc => new Amount(getBalance(acc, selectedAsset)).gte('1')) + + if(!account) return + + history.push( + WalletRoutes.SendPage.replace(':chainId?', selectedAssetsNetwork.chainId) + .replace(':accountAddress?', account.address) + .replace(':contractAddress?', selectedAsset.contractAddress) + .replace(':tokenId?', selectedAsset.tokenId) + ) + }, [selectedAsset, accounts, selectedAssetsNetwork]) // effects React.useEffect(() => { @@ -496,6 +511,7 @@ export const PortfolioAsset = (props: Props) => { onBack={goBack} assetName={selectedAsset?.name} tokenId={selectedAsset?.tokenId} + showSendButton={!new Amount(fullAssetBalances?.assetBalance || '').isZero()} onSend={onSend} /> } diff --git a/components/brave_wallet_ui/constants/types.ts b/components/brave_wallet_ui/constants/types.ts index f50015813980c..188fe475455d3 100644 --- a/components/brave_wallet_ui/constants/types.ts +++ b/components/brave_wallet_ui/constants/types.ts @@ -810,7 +810,12 @@ export enum WalletRoutes { Swap = '/swap', // send - Send = '/send', + SendPageStart = '/send', + SendPage = '/send/' + + ':chainId?/' + + ':accountAddress?/' + + ':contractAddress?/' + + ':tokenId?', // dev bitcoin screen DevBitcoin = '/dev-bitcoin', diff --git a/components/brave_wallet_ui/options/nav-options.ts b/components/brave_wallet_ui/options/nav-options.ts index 6257b990d5c89..4e0a8432ba83b 100644 --- a/components/brave_wallet_ui/options/nav-options.ts +++ b/components/brave_wallet_ui/options/nav-options.ts @@ -17,7 +17,7 @@ export const BuySendSwapDepositOptions: NavOption[] = [ id: 'send', name: 'braveWalletSend', icon: 'send', - route: WalletRoutes.Send + route: WalletRoutes.SendPageStart }, { id: 'swap', diff --git a/components/brave_wallet_ui/page/container.tsx b/components/brave_wallet_ui/page/container.tsx index 1bb0e783ba194..860eab9119295 100644 --- a/components/brave_wallet_ui/page/container.tsx +++ b/components/brave_wallet_ui/page/container.tsx @@ -139,7 +139,7 @@ export const Container = () => { walletLocation.includes(WalletRoutes.PortfolioNFTs) || walletLocation.includes(WalletRoutes.Market) || walletLocation.includes(WalletRoutes.Swap) || - walletLocation.includes(WalletRoutes.Send) || + walletLocation.includes(WalletRoutes.SendPageStart) || walletLocation.includes(WalletRoutes.LocalIpfsNode || walletLocation.includes(WalletRoutes.InspectNfts)) ) { @@ -153,7 +153,7 @@ export const Container = () => { if (toobarElement && rootElement) { if ( walletLocation === WalletRoutes.Swap || - walletLocation === WalletRoutes.Send || + walletLocation === WalletRoutes.SendPageStart || walletLocation.includes(WalletRoutes.DepositFundsPage) || walletLocation.includes(WalletRoutes.FundWalletPage) || walletLocation.includes(WalletRoutes.LocalIpfsNode) || @@ -296,7 +296,7 @@ export const Container = () => { )} {!isWalletLocked && - + diff --git a/components/brave_wallet_ui/page/screens/send/send/send.tsx b/components/brave_wallet_ui/page/screens/send/send/send.tsx index 7ee485269e772..f9f1d67e37350 100644 --- a/components/brave_wallet_ui/page/screens/send/send/send.tsx +++ b/components/brave_wallet_ui/page/screens/send/send/send.tsx @@ -4,6 +4,8 @@ // you can obtain one at https://mozilla.org/MPL/2.0/. import * as React from 'react' +import { useParams } from 'react-router' +import { useDispatch } from 'react-redux' import { skipToken } from '@reduxjs/toolkit/query/react' // Messages @@ -12,6 +14,9 @@ import { ENSOffchainLookupMessage, FailedChecksumMessage } from '../send-ui-mess // Types import { BraveWallet, SendOptionTypes, AddressMessageInfo } from '../../../../constants/types' +// Actions +import { WalletActions } from '../../../../common/actions' + // Selectors import { WalletSelectors } from '../../../../common/selectors' import { useUnsafeWalletSelector } from '../../../../common/hooks/use-safe-selector' @@ -29,7 +34,7 @@ import { endsWithAny } from '../../../../utils/string-utils' // Hooks import { usePreset, useBalanceUpdater, useSend } from '../../../../common/hooks' import { useOnClickOutside } from '../../../../common/hooks/useOnClickOutside' -import { useGetNetworkQuery } from '../../../../common/slices/api.slice' +import { useGetNetworkQuery, useSetNetworkMutation } from '../../../../common/slices/api.slice' // Styled Components import { @@ -78,8 +83,18 @@ export const Send = (props: Props) => { const selectedAccount = useUnsafeWalletSelector(WalletSelectors.selectedAccount) const spotPrices = useUnsafeWalletSelector(WalletSelectors.transactionSpotPrices) const defaultCurrencies = useUnsafeWalletSelector(WalletSelectors.defaultCurrencies) + const accounts = useUnsafeWalletSelector(WalletSelectors.accounts) + + // routing + const { chainId, accountAddress, contractAddress, tokenId } = useParams<{ + chainId?: string + accountAddress?: string + contractAddress?: string + tokenId?: string + }>() // Hooks + const dispatch = useDispatch() useBalanceUpdater() const { @@ -98,13 +113,15 @@ export const Send = (props: Props) => { submitSend, selectSendAsset, searchingForDomain, - processAddressOrUrl + processAddressOrUrl, + sendAssetOptions } = useSend(true) - // Queries + // Queries & Mutations const { data: selectedTokensNetwork } = useGetNetworkQuery( selectedSendAsset ?? skipToken ) + const [setNetwork] = useSetNetworkMutation() // Refs const ref = React.createRef() @@ -320,6 +337,23 @@ export const Send = (props: Props) => { showEnsOffchainWarning }, [toAddressOrUrl, searchingForDomain, showEnsOffchainWarning]) + const selectedAssetFromParams = React.useMemo(() => { + if (!contractAddress) return + + return sendAssetOptions.find((option) => + tokenId + ? option.contractAddress.toLowerCase() === + contractAddress.toLowerCase() && option.tokenId === tokenId + : option.contractAddress.toLowerCase() === contractAddress.toLowerCase() + ) + }, [sendAssetOptions, contractAddress, tokenId]) + + const accountFromParams = React.useMemo(() => { + return accounts.find( + (account) => account.address === accountAddress + ) + }, [accountAddress, accounts]) + // Effects React.useEffect(() => { // Keeps track of the Swap Containers Height to update @@ -344,6 +378,28 @@ export const Send = (props: Props) => { } }, [selectedTokensNetwork]) + React.useEffect(() => { + // check if the user has selected an asset + if (!chainId || !selectedAssetFromParams || !accountFromParams || selectedSendAsset) return + + dispatch(WalletActions.selectAccount(accountFromParams)) + setNetwork({ + chainId: chainId, + coin: selectedAssetFromParams.coin + }) + .catch((e) => console.error(e)) + + setSelectedSendOption(tokenId ? 'nft' : 'token') + selectSendAsset(selectedAssetFromParams) + }, [ + setSelectedSendOption, + selectSendAsset, + selectedSendAsset, + chainId, + selectedAssetFromParams, + accountFromParams + ]) + // render return ( <> diff --git a/components/brave_wallet_ui/utils/string-utils.ts b/components/brave_wallet_ui/utils/string-utils.ts index 7d4fea71acf74..7b498bb391e87 100644 --- a/components/brave_wallet_ui/utils/string-utils.ts +++ b/components/brave_wallet_ui/utils/string-utils.ts @@ -89,7 +89,7 @@ export const getWalletLocationTitle = (location: string) => { if (location === WalletRoutes.Swap) { return getLocale('braveWalletSwap') } - if (location === WalletRoutes.Send) { + if (location === WalletRoutes.SendPageStart) { return getLocale('braveWalletSend') } /** Wallet */