diff --git a/components/brave_wallet/browser/brave_wallet_constants.h b/components/brave_wallet/browser/brave_wallet_constants.h
index f193fc112513..717f2a3c0834 100644
--- a/components/brave_wallet/browser/brave_wallet_constants.h
+++ b/components/brave_wallet/browser/brave_wallet_constants.h
@@ -412,6 +412,8 @@ inline constexpr webui::LocalizedString kLocalizedStrings[] = {
{"braveWalletAccountsEditVisibleAssets",
IDS_BRAVE_WALLET_ACCOUNTS_EDIT_VISIBLE_ASSETS},
{"braveWalletAccountBalance", IDS_BRAVE_WALLET_ACCOUNT_BALANCE},
+ {"braveWalletViewAddressOn", IDS_BRAVE_WALLET_VIEW_ADDRESS_ON},
+ {"braveWalletNetworkExplorer", IDS_BRAVE_WALLET_NETWORK_EXPLORER},
{"braveWalletAddAccountCreate", IDS_BRAVE_WALLET_ADD_ACCOUNT_CREATE},
{"braveWalletCreateAccount", IDS_BRAVE_WALLET_CREATE_ACCOUNT},
{"braveWalletCreateAccountButton", IDS_BRAVE_WALLET_CREATE_ACCOUNT_BUTTON},
diff --git a/components/brave_wallet_ui/components/desktop/card-headers/account-details-header.tsx b/components/brave_wallet_ui/components/desktop/card-headers/account-details-header.tsx
index 437cb9c851db..4e6db51a12d5 100644
--- a/components/brave_wallet_ui/components/desktop/card-headers/account-details-header.tsx
+++ b/components/brave_wallet_ui/components/desktop/card-headers/account-details-header.tsx
@@ -192,6 +192,17 @@ export const AccountDetailsHeader = (props: Props) => {
(option: AccountButtonOptionsObjectType) => option.id !== 'privateKey'
)
}
+ // We are currently not able to support viewing a
+ // BTC or ZEC account on a block explorer.
+ // Link to issue https://github.com/brave/brave-browser/issues/39699
+ if (
+ account.accountId.coin === BraveWallet.CoinType.BTC ||
+ account.accountId.coin === BraveWallet.CoinType.ZEC
+ ) {
+ options = options.filter(
+ (option: AccountButtonOptionsObjectType) => option.id !== 'explorer'
+ )
+ }
return options
}, [account])
diff --git a/components/brave_wallet_ui/components/desktop/popup-modals/style.ts b/components/brave_wallet_ui/components/desktop/popup-modals/style.ts
index 19e022130aed..f09a28e76487 100644
--- a/components/brave_wallet_ui/components/desktop/popup-modals/style.ts
+++ b/components/brave_wallet_ui/components/desktop/popup-modals/style.ts
@@ -75,6 +75,9 @@ export const Header = styled.div<{
export const Title = styled.span`
color: ${leo.color.text.primary};
font: ${leo.font.heading.h2};
+ @media screen and (max-width: ${layoutPanelWidth}px) {
+ font: ${leo.font.heading.h4};
+ }
`
export const HeaderButton = styled(WalletButton)`
diff --git a/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/network_button.tsx b/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/network_button.tsx
new file mode 100644
index 000000000000..7fc3f3452090
--- /dev/null
+++ b/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/network_button.tsx
@@ -0,0 +1,56 @@
+// Copyright (c) 2024 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at https://mozilla.org/MPL/2.0/.
+import * as React from 'react'
+
+// Types
+import { BraveWallet } from '../../../../constants/types'
+
+// Custom hooks
+import { useExplorer } from '../../../../common/hooks/explorer'
+
+// Utils
+import { getLocale } from '../../../../../common/locale'
+
+// Components
+import { CreateNetworkIcon } from '../../../shared/create-network-icon'
+
+// Styles
+import { Button, LaunchIcon } from './view_on_block_explorer_modal.style'
+import { Text, Row } from '../../../shared/style'
+
+interface Props {
+ network: BraveWallet.NetworkInfo
+ address: string
+}
+
+export const NetworkButton = (props: Props) => {
+ const { network, address } = props
+
+ // Hooks
+ const onClickViewOnBlockExplorer = useExplorer(network)
+
+ return (
+
+ )
+}
diff --git a/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/view_on_block_explorer_modal.style.ts b/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/view_on_block_explorer_modal.style.ts
new file mode 100644
index 000000000000..c4faca9a4236
--- /dev/null
+++ b/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/view_on_block_explorer_modal.style.ts
@@ -0,0 +1,52 @@
+// Copyright (c) 2024 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at https://mozilla.org/MPL/2.0/.
+import styled from 'styled-components'
+import * as leo from '@brave/leo/tokens/css/variables'
+import Icon from '@brave/leo/react/icon'
+
+// Shared Styled
+import { Row, WalletButton, Column, Text } from '../../../shared/style'
+
+export const StyledWrapper = styled(Column)`
+ overflow: hidden;
+`
+
+export const AccountInfoRow = styled(Row)`
+ background-color: ${leo.color.container.highlight};
+ border-radius: ${leo.radius.xl};
+ padding: 8px;
+`
+
+export const AddressText = styled(Text)`
+ word-break: break-all;
+`
+
+export const Button = styled(WalletButton)`
+ cursor: pointer;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-between;
+ align-items: center;
+ background: none;
+ background-color: none;
+ outline: none;
+ border: none;
+ border-radius: ${leo.radius.m};
+ width: 100%;
+ padding: 16px;
+ --icon-display: none;
+ &:hover {
+ background-color: ${leo.color.container.highlight};
+ --icon-display: block;
+ }
+`
+
+export const LaunchIcon = styled(Icon).attrs({
+ name: 'launch'
+})`
+ display: var(--icon-display);
+ --leo-icon-size: 16px;
+ color: ${leo.color.icon.interactive};
+`
diff --git a/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/view_on_block_explorer_modal.tsx b/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/view_on_block_explorer_modal.tsx
new file mode 100644
index 000000000000..b9214580711c
--- /dev/null
+++ b/components/brave_wallet_ui/components/desktop/popup-modals/view_on_block_explorer_modal/view_on_block_explorer_modal.tsx
@@ -0,0 +1,118 @@
+// Copyright (c) 2024 The Brave Authors. All rights reserved.
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this file,
+// You can obtain one at https://mozilla.org/MPL/2.0/.
+import * as React from 'react'
+
+// Types
+import { BraveWallet } from '../../../../constants/types'
+
+// Queries
+import {
+ useGetVisibleNetworksQuery //
+} from '../../../../common/slices/api.slice'
+
+// Utils
+import { getLocale } from '../../../../../common/locale'
+import {
+ getNetworkId //
+} from '../../../../common/slices/entities/network.entity'
+
+// Components
+import { PopupModal } from '../../popup-modals/index'
+import {
+ CreateAccountIcon //
+} from '../../../shared/create-account-icon/create-account-icon'
+import { NetworkButton } from './network_button'
+
+// Styles
+import {
+ AccountInfoRow,
+ StyledWrapper,
+ AddressText
+} from './view_on_block_explorer_modal.style'
+import { Column, Text, Row, ScrollableColumn } from '../../../shared/style'
+
+interface Props {
+ account: BraveWallet.AccountInfo
+ onClose: () => void
+}
+
+export const ViewOnBlockExplorerModal = (props: Props) => {
+ const { account, onClose } = props
+
+ // Queries
+ const { data: visibleNetworks = [] } = useGetVisibleNetworksQuery()
+
+ // Memos
+ const networksByAccountCoinType = React.useMemo(() => {
+ return visibleNetworks.filter(
+ (network) => network.coin === account.accountId.coin
+ )
+ }, [visibleNetworks, account])
+
+ return (
+
+
+
+
+
+
+ {account.name}
+
+
+ {account.address}
+
+
+
+
+
+ {getLocale('braveWalletViewAddressOn')}
+
+
+
+ {networksByAccountCoinType.map((network) => (
+
+ ))}
+
+
+
+ )
+}
diff --git a/components/brave_wallet_ui/components/desktop/views/accounts/account.tsx b/components/brave_wallet_ui/components/desktop/views/accounts/account.tsx
index b0208e5d3d82..77a4d0b129f0 100644
--- a/components/brave_wallet_ui/components/desktop/views/accounts/account.tsx
+++ b/components/brave_wallet_ui/components/desktop/views/accounts/account.tsx
@@ -20,7 +20,8 @@ import {
CoinTypesMap,
WalletRoutes,
AccountModalTypes,
- AccountPageTabs
+ AccountPageTabs,
+ SupportedTestNetworks
} from '../../../../constants/types'
// utils
@@ -86,6 +87,9 @@ import {
import {
EmptyTokenListState //
} from '../portfolio/components/empty-token-list-state/empty-token-list-state'
+import {
+ ViewOnBlockExplorerModal //
+} from '../../popup-modals/view_on_block_explorer_modal/view_on_block_explorer_modal'
// options
import { AccountDetailsOptions } from '../../../../options/nav-options'
@@ -105,11 +109,19 @@ import {
import {
useBalancesFetcher //
} from '../../../../common/hooks/use-balances-fetcher'
+import { useExplorer } from '../../../../common/hooks/explorer'
// Actions
import { AccountsTabActions } from '../../../../page/reducers/accounts-tab-reducer'
import { useAccountsQuery } from '../../../../common/slices/api.slice.extra'
+const INDIVIDUAL_TESTNET_ACCOUNT_KEYRING_IDS = [
+ BraveWallet.KeyringId.kBitcoin84Testnet,
+ BraveWallet.KeyringId.kBitcoinImportTestnet,
+ BraveWallet.KeyringId.kFilecoinTestnet,
+ BraveWallet.KeyringId.kZCashTestnet
+]
+
const removedNFTsRouteOptions = AccountDetailsOptions.filter(
(option) => option.id !== 'nfts'
)
@@ -169,10 +181,42 @@ export const Account = () => {
// state
const [showAddNftModal, setShowAddNftModal] = React.useState(false)
+ const [showViewOnBlockExplorerModal, setShowViewOnBlockExplorerModal] =
+ React.useState(false)
- // custom hooks
+ // custom hooks & memos
const scrollIntoView = useScrollIntoView()
+ const networksFilteredByAccountsCoinType = React.useMemo(() => {
+ return !selectedAccount
+ ? []
+ : networkList.filter(
+ (network) => network.coin === selectedAccount.accountId.coin
+ )
+ }, [networkList, selectedAccount])
+
+ const networkForSelectedAccount = React.useMemo(() => {
+ if (!selectedAccount) {
+ return
+ }
+ // BTC, ZEC and FIL use different accounts for testnet.
+ // This checks if the selectedAccount is a testnet account
+ // and finds the appropriate network to use.
+ if (
+ INDIVIDUAL_TESTNET_ACCOUNT_KEYRING_IDS.includes(
+ selectedAccount.accountId.keyringId
+ )
+ )
+ return networksFilteredByAccountsCoinType.find((network) =>
+ SupportedTestNetworks.includes(network.chainId)
+ )
+ return networksFilteredByAccountsCoinType.find(
+ (network) => !SupportedTestNetworks.includes(network.chainId)
+ )
+ }, [selectedAccount, networksFilteredByAccountsCoinType])
+
+ const onClickViewOnBlockExplorer = useExplorer(networkForSelectedAccount)
+
// memos
const transactionList = React.useMemo(() => {
return sortTransactionByDate(unsortedTransactionList, 'descending')
@@ -349,11 +393,36 @@ export const Account = () => {
onRemoveAccount()
return
}
+ if (
+ option === 'explorer' &&
+ // Only show the Block Explorer modal if there is
+ // more than 1 network to show and if CoinType is
+ // ETH or SOL.
+ networksFilteredByAccountsCoinType.length > 1 &&
+ (selectedAccount?.accountId.coin === BraveWallet.CoinType.ETH ||
+ selectedAccount?.accountId.coin === BraveWallet.CoinType.SOL)
+ ) {
+ setShowViewOnBlockExplorerModal(true)
+ return
+ }
+ if (option === 'explorer' && selectedAccount?.accountId.address) {
+ onClickViewOnBlockExplorer(
+ 'address',
+ selectedAccount.accountId.address
+ )()
+ return
+ }
dispatch(AccountsTabActions.setShowAccountModal(true))
dispatch(AccountsTabActions.setAccountModalType(option))
dispatch(AccountsTabActions.setSelectedAccount(selectedAccount))
},
- [dispatch, onRemoveAccount, selectedAccount]
+ [
+ dispatch,
+ onRemoveAccount,
+ networksFilteredByAccountsCoinType,
+ selectedAccount,
+ onClickViewOnBlockExplorer
+ ]
)
const checkIsTransactionFocused = React.useCallback(
@@ -527,6 +596,13 @@ export const Account = () => {
>
)}
+ {showViewOnBlockExplorerModal && (
+ setShowViewOnBlockExplorerModal(false)}
+ />
+ )}
+
{showAddNftModal && (
setShowAddNftModal(false)}
diff --git a/components/brave_wallet_ui/constants/types.ts b/components/brave_wallet_ui/constants/types.ts
index dc0171c9ad15..c5955317303d 100644
--- a/components/brave_wallet_ui/constants/types.ts
+++ b/components/brave_wallet_ui/constants/types.ts
@@ -840,6 +840,7 @@ export type AccountModalTypes =
| 'details'
| 'remove'
| 'buy'
+ | 'explorer'
export interface AccountButtonOptionsObjectType {
name: string
diff --git a/components/brave_wallet_ui/options/account-details-menu-options.ts b/components/brave_wallet_ui/options/account-details-menu-options.ts
index a13b95afe2dc..99af0d7648c6 100644
--- a/components/brave_wallet_ui/options/account-details-menu-options.ts
+++ b/components/brave_wallet_ui/options/account-details-menu-options.ts
@@ -11,6 +11,11 @@ export const AccountDetailsMenuOptions: AccountButtonOptionsObjectType[] = [
name: 'braveWalletAllowSpendEditButton',
icon: 'edit-pencil'
},
+ {
+ id: 'explorer',
+ name: 'braveWalletTransactionExplorer',
+ icon: 'web3-blockexplorer'
+ },
{
id: 'deposit',
name: 'braveWalletAccountsDeposit',
diff --git a/components/brave_wallet_ui/stories/locale.ts b/components/brave_wallet_ui/stories/locale.ts
index 6460c585a0e8..937a3e640e24 100644
--- a/components/brave_wallet_ui/stories/locale.ts
+++ b/components/brave_wallet_ui/stories/locale.ts
@@ -395,6 +395,8 @@ provideStrings({
braveWalletAccountsAssets: 'Assets',
braveWalletAccountsEditVisibleAssets: 'Visible assets',
braveWalletAccountBalance: 'Account balance',
+ braveWalletViewAddressOn: 'View address on:',
+ braveWalletNetworkExplorer: '$1 Explorer',
// Add Account Options
braveWalletCreateAccount: 'Create $1 account',
diff --git a/components/resources/wallet_strings.grdp b/components/resources/wallet_strings.grdp
index 6f3250469f1a..1f471e6efb0c 100644
--- a/components/resources/wallet_strings.grdp
+++ b/components/resources/wallet_strings.grdp
@@ -230,6 +230,8 @@
Assets
Visible assets
Account balance
+ View address on:
+ Ethereum Mainnet$1 Explorer
Create
Create account
Create Ethereum$1 account
diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn
index 298ca800199e..b03a6b5851a5 100644
--- a/ui/webui/resources/BUILD.gn
+++ b/ui/webui/resources/BUILD.gn
@@ -383,6 +383,7 @@ leo_icons = [
"warning-triangle-filled.svg",
"warning-triangle-outline.svg",
"web3.svg",
+ "web3-blockexplorer.svg",
"web3-bridge.svg",
"widget-generic.svg",
"window-content.svg",