diff --git a/e2e/fixtures/pages/overview.ts b/e2e/fixtures/pages/overview.ts index 2cc71983ea..aa111b6453 100644 --- a/e2e/fixtures/pages/overview.ts +++ b/e2e/fixtures/pages/overview.ts @@ -15,6 +15,8 @@ export class OverviewPage extends ExtensionPage { - img - link "Rewards": - img + - link "Search": + - img - link "Settings": - img - button "Open Sidepanel": @@ -45,10 +47,11 @@ export class OverviewPage extends ExtensionPage { - link "NFTs" - link "History" - link "Perks" - - img "Empty Wallet Cover" - - text: Fund your wallet Buy or transfer crypto to get started - - link "Buy Crypto with Card" - - link "Receive from Another Wallet" + - button "All Networks": + - img + - text: Get Started By adding crypto to your wallet + - button "Fund": + - img `); } } diff --git a/src/modules/statsig/statsig.client.ts b/src/modules/statsig/statsig.client.ts index cc592f19e9..b2d0636646 100644 --- a/src/modules/statsig/statsig.client.ts +++ b/src/modules/statsig/statsig.client.ts @@ -1,6 +1,8 @@ import { useQuery } from '@tanstack/react-query'; import { getStatsigExperiment, getStatsigFeatureGate } from './shared'; +export const ONRAMP_EXPERIMENT_NAME = 'web-onramp_flow'; + export function useStatsigExperiment( name: string, { diff --git a/src/shared/analytics/analytics.background.ts b/src/shared/analytics/analytics.background.ts index d500546b11..43029a7b7e 100644 --- a/src/shared/analytics/analytics.background.ts +++ b/src/shared/analytics/analytics.background.ts @@ -222,12 +222,15 @@ function trackAppEvents({ account }: { account: Account }) { if (!preferences.analyticsEnabled) { return; } - const { bannerName, pathname, walletAddress } = data; + const { bannerName, pathname, walletAddress, bannerSource, bannerType } = + data; const params = createParams({ request_name: 'banner_clicked', screen_name: pathname, banner_name: bannerName, wallet_address: walletAddress, + ...(bannerSource ? { source: bannerSource } : null), + ...(bannerType ? { banner_type: bannerType } : null), }); const event_name = 'General: Banner Clicked'; const mixpanelParams = omit(params, ['request_name', 'wallet_address']); diff --git a/src/shared/types/button-events.ts b/src/shared/types/button-events.ts index 5a41cefac2..5f4d45a589 100644 --- a/src/shared/types/button-events.ts +++ b/src/shared/types/button-events.ts @@ -1,6 +1,6 @@ // Shared event types for analytics -export type ButtonScope = 'General' | 'Loaylty' | 'General'; +export type ButtonScope = 'General' | 'Loaylty'; export type ButtonName = | 'Claim XP' | 'Rewards' @@ -8,6 +8,9 @@ export type ButtonName = | 'Rate Tooltip' | 'Quote List Bottom Description' | 'Premium Features' + | 'Buy Crypto' + | 'Receive Crypto' + | 'Fund' | 'Buy Premium'; export interface ButtonClickedParams { @@ -17,10 +20,14 @@ export interface ButtonClickedParams { walletAddress?: string; } -export type BannerName = 'Buy Premium'; +export type BannerName = 'Buy Premium' | 'Get started'; +type BannerType = 'Fund_wallet'; +type BannerSource = 'Internal'; export interface BannerClickedParams { pathname: string; bannerName: BannerName; + bannerType?: BannerType; + bannerSource?: BannerSource; walletAddress?: string; } diff --git a/src/ui/assets/actions/fund.svg b/src/ui/assets/actions/fund.svg new file mode 100644 index 0000000000..655ba95dba --- /dev/null +++ b/src/ui/assets/actions/fund.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/ui/assets/arrow-circle-outlined.svg b/src/ui/assets/arrow-circle-outlined.svg new file mode 100644 index 0000000000..bdfcce2c7f --- /dev/null +++ b/src/ui/assets/arrow-circle-outlined.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/ui/assets/identity.svg b/src/ui/assets/identity.svg new file mode 100644 index 0000000000..85fd4424dd --- /dev/null +++ b/src/ui/assets/identity.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/ui/pages/Overview/ActionButtonsRow/ActionButtonsRow.tsx b/src/ui/pages/Overview/ActionButtonsRow/ActionButtonsRow.tsx index e2e8bbfb6e..943ba5037d 100644 --- a/src/ui/pages/Overview/ActionButtonsRow/ActionButtonsRow.tsx +++ b/src/ui/pages/Overview/ActionButtonsRow/ActionButtonsRow.tsx @@ -1,12 +1,14 @@ import browser from 'webextension-polyfill'; import type { ComponentPropsWithoutRef, ElementType } from 'react'; -import React from 'react'; +import React, { useRef } from 'react'; +import { useLocation } from 'react-router-dom'; import classNames from 'classnames'; -import { useMutation, useQuery } from '@tanstack/react-query'; +import { useQuery } from '@tanstack/react-query'; import SwapIcon from 'jsx:src/ui/assets/actions/swap.svg'; import SendIcon from 'jsx:src/ui/assets/actions/send.svg'; -import ReceiveIcon from 'jsx:src/ui/assets/actions/receive.svg'; import BridgeIcon from 'jsx:src/ui/assets/actions/bridge.svg'; +import FundIcon from 'jsx:src/ui/assets/actions/fund.svg'; +import ReceiveIcon from 'jsx:src/ui/assets/actions/receive.svg'; import BuyIcon from 'jsx:src/ui/assets/actions/buy.svg'; import { UnstyledAnchor } from 'src/ui/ui-kit/UnstyledAnchor'; import { walletPort } from 'src/ui/shared/channels'; @@ -16,8 +18,18 @@ import { HStack } from 'src/ui/ui-kit/HStack'; import { UIText } from 'src/ui/ui-kit/UIText'; import { Button } from 'src/ui/ui-kit/Button'; import { WithMainnetOnlyWarningDialog } from 'src/ui/features/testnet-mode/MainnetOnlyWarningDialog'; +import { type HTMLDialogElementInterface } from 'src/ui/ui-kit/ModalDialogs/HTMLDialogElementInterface'; +import { UnstyledButton } from 'src/ui/ui-kit/UnstyledButton'; +import { emitter } from 'src/ui/shared/events'; +import { + ONRAMP_EXPERIMENT_NAME, + useStatsigExperiment, +} from 'src/modules/statsig/statsig.client'; +import { AddFundsOptionsDialog } from '../../Receive/AddFundsOptionsDialog'; import * as s from './styles.module.css'; +const ZERION_ORIGIN = 'https://app.zerion.io'; + function ActionButton({ as, icon, @@ -39,52 +51,126 @@ function ActionButton({ ); } -const ZERION_ORIGIN = 'https://app.zerion.io'; +function acceptOrigin(params: { address: string; origin: string }) { + return walletPort.request('acceptOrigin', params); +} + +export function useOpenAndConnectToZerion({ + address, +}: { + address: string | null; +}) { + const { data: activeTabs } = useQuery({ + queryKey: ['browser/activeTab'], + queryFn: () => browser.tabs.query({ active: true, currentWindow: true }), + }); + const activeTab = activeTabs ? activeTabs[0] : null; + const handleAnchorClick = (event: React.MouseEvent) => { + if (!address) { + return; + } + acceptOrigin({ origin: ZERION_ORIGIN, address }); + const href = event.currentTarget.getAttribute('href'); + const activeTabUrl = activeTab?.url ? new URL(activeTab.url) : null; + if (href && activeTab && activeTabUrl?.origin == ZERION_ORIGIN) { + event.preventDefault(); + browser.tabs.update(activeTab.id, { url: href }); + } + }; + return { handleAnchorClick }; +} export function ActionButtonsRow() { + const { pathname } = useLocation(); const { data: wallet } = useQuery({ queryKey: ['wallet/uiGetCurrentWallet'], queryFn: () => { return walletPort.request('uiGetCurrentWallet'); }, }); - const { mutate: acceptOrigin } = useMutation({ - mutationFn: async ({ - address, - origin, - }: { - address: string; - origin: string; - }) => { - return walletPort.request('acceptOrigin', { origin, address }); - }, - }); const addWalletParams = useWalletParams(wallet); - - const { data: activeTabs } = useQuery({ - queryKey: ['browser/activeTab'], - queryFn: () => browser.tabs.query({ active: true, currentWindow: true }), - }); - const activeTab = activeTabs ? activeTabs[0] : null; - const { mutate: updateTab } = useMutation({ - mutationFn: async ({ tab, url }: { tab: browser.Tabs.Tab; url: string }) => - browser.tabs.update(tab.id, { url }), + const fundOptionsDialogRef = useRef(null); + const { handleAnchorClick } = useOpenAndConnectToZerion({ + address: wallet?.address ?? null, }); + + const statsigExperimentQuery = useStatsigExperiment(ONRAMP_EXPERIMENT_NAME); + if (statsigExperimentQuery.isLoading) { + return
; + } + if (!addWalletParams || !wallet) { return null; } - const performAction = (event: React.MouseEvent) => { - acceptOrigin({ origin: ZERION_ORIGIN, address: wallet.address }); - const href = event.currentTarget.getAttribute('href'); - const activeTabUrl = activeTab?.url ? new URL(activeTab.url) : null; - if (href && activeTab && activeTabUrl?.origin == ZERION_ORIGIN) { - event.preventDefault(); - updateTab({ tab: activeTab, url: href }); - } - }; + const receiveButton = ( + } + to={`/receive?address=${wallet.address}`} + /> + ); + const sendButton = ( + } + to="/send-form" + /> + ); + + const bridgeButton = ( + + message="Testnets are not supported in Bridge" + render={({ handleClick }) => ( + } + to="/bridge-form" + onClick={(event) => { + handleClick(event); + }} + /> + )} + /> + ); + const fundButton = ( + } + onClick={() => { + fundOptionsDialogRef.current?.showModal(); + + emitter.emit('buttonClicked', { + buttonName: 'Fund', + buttonScope: 'General', + pathname, + walletAddress: wallet.address, + }); + }} + /> + ); + + const buyButton = ( + } + href={`${ZERION_ORIGIN}/deposit?${addWalletParams}`} + onClick={handleAnchorClick} + target="_blank" + rel="noopener noreferrer" + /> + ); return ( -
+
+
    -
  • - } - to="/send-form" - /> -
  • -
  • - } - to={`/receive?address=${wallet.address}`} - /> -
  • -
  • + {statsigExperimentQuery.data?.group_name?.toLowerCase() === 'test' ? ( + <> +
  • {fundButton}
  • +
  • {sendButton}
  • +
  • {bridgeButton}
  • + + ) : ( + <> +
  • {sendButton}
  • +
  • {receiveButton}
  • +
  • {bridgeButton}
  • +
  • {buyButton}
  • + + )} +
  • - message="Testnets are not supported in Bridge" + message="Testnets are not supported in Swap" render={({ handleClick }) => ( - } - to="/bridge-form" onClick={(event) => { handleClick(event); }} - /> - )} - /> -
  • -
  • - } - href={`${ZERION_ORIGIN}/deposit?${addWalletParams}`} - onClick={performAction} - target="_blank" - rel="noopener noreferrer" - /> -
  • -
  • - - message="Testnets are not supported in Swap" - render={({ handleClick }) => ( - <> - } - to="/swap-form" - onClick={(event) => { - handleClick(event); - }} - /> -
    - -
    - + to="/swap-form" + style={{ + borderRadius: 24, + width: '100%', + paddingInline: 0, + ['--button-background' as string]: 'var(--black)', + ['--button-text' as string]: 'var(--white)', + ['--button-background-hover' as string]: 'var(--neutral-800)', + }} + > + +
    + +
    + Swap +
    + )} />
  • diff --git a/src/ui/pages/Overview/ActionButtonsRow/styles.module.css b/src/ui/pages/Overview/ActionButtonsRow/styles.module.css index c861979220..6b42721089 100644 --- a/src/ui/pages/Overview/ActionButtonsRow/styles.module.css +++ b/src/ui/pages/Overview/ActionButtonsRow/styles.module.css @@ -1,34 +1,11 @@ -.containerRoot { - container-name: action-buttons-row; - container-type: inline-size; -} - .list { - display: grid; + display: flex; gap: 8; - grid-template-columns: repeat(5, 48px); justify-content: space-between; } -.hideWhenSmall { - display: none; -} - -@container action-buttons-row (width > 390px) { - .list { - grid-template-columns: repeat(4, 48px) minmax(100px, 176px); - justify-content: start; - } - .hideWhenSmall { - display: block; - } - .showWhenSmall { - display: none; - } -} - .actionButton { - --btn-bg-color: var(--neutral-200); + --btn-bg-color: var(--neutral-100); --btn-active-bg-color: var(--neutral-300); --btn-color: var(--neutral-800); } diff --git a/src/ui/pages/Overview/Positions/EmptyPositionsView.tsx b/src/ui/pages/Overview/Positions/EmptyPositionsView.tsx index 6b71c40392..3a71c8b9e7 100644 --- a/src/ui/pages/Overview/Positions/EmptyPositionsView.tsx +++ b/src/ui/pages/Overview/Positions/EmptyPositionsView.tsx @@ -1,22 +1,25 @@ -import React from 'react'; -import { useMutation, useQuery } from '@tanstack/react-query'; -import { useNavigate } from 'react-router-dom'; -import { normalizeAddress } from 'src/shared/normalizeAddress'; -import { getAddressType } from 'src/shared/wallet/classifiers'; +import React, { useRef } from 'react'; +import { useQuery } from '@tanstack/react-query'; +import ArrowCircleIcon from 'jsx:src/ui/assets/arrow-circle-outlined.svg'; import { EmptyView } from 'src/ui/components/EmptyView'; import { usePreferences } from 'src/ui/features/preferences'; import { walletPort } from 'src/ui/shared/channels'; -import { setCurrentAddress } from 'src/ui/shared/requests/setCurrentAddress'; -import { useWalletParams } from 'src/ui/shared/requests/useWalletParams'; import { Button } from 'src/ui/ui-kit/Button'; import { UIText } from 'src/ui/ui-kit/UIText'; -import { UnstyledAnchor } from 'src/ui/ui-kit/UnstyledAnchor'; -import { UnstyledLink } from 'src/ui/ui-kit/UnstyledLink'; import { VStack } from 'src/ui/ui-kit/VStack'; +import { HStack } from 'src/ui/ui-kit/HStack'; +import { type HTMLDialogElementInterface } from 'src/ui/ui-kit/ModalDialogs/HTMLDialogElementInterface'; +import { emitter } from 'src/ui/shared/events'; +import { useLocation } from 'react-router-dom'; +import { + ONRAMP_EXPERIMENT_NAME, + useStatsigExperiment, +} from 'src/modules/statsig/statsig.client'; +import { AddFundsOptionsDialog } from '../../Receive/AddFundsOptionsDialog'; +import { EmptyPositionsViewLegacy } from './EmptyPositionsViewLegacy'; -const ZERION_ORIGIN = 'https://app.zerion.io'; - -export function EmptyPositionsView() { +export function EmptyPositionsViewNew() { + const { pathname } = useLocation(); const { data: wallet } = useQuery({ queryKey: ['wallet/uiGetCurrentWallet'], queryFn: () => { @@ -24,110 +27,79 @@ export function EmptyPositionsView() { }, }); - const { data: walletGroups, isLoading } = useQuery({ - queryKey: ['wallet/uiGetWalletGroups'], - queryFn: () => walletPort.request('uiGetWalletGroups'), - useErrorBoundary: true, - suspense: false, - }); - const { preferences } = usePreferences(); - const addWalletParams = useWalletParams(wallet); - const navigate = useNavigate(); + const dialogRef = useRef(null); const isTestnetMode = preferences?.testnetMode?.on; - const goToBridgeMutation = useMutation({ - mutationFn: async () => { - const solanaAddress = wallet?.address; - let ethereumAddress: string | null = null; - if (walletGroups) { - for (const group of walletGroups) { - for (const wallet of group.walletContainer.wallets) { - const address = normalizeAddress(wallet.address); - if (getAddressType(address) === 'evm') { - ethereumAddress = address; - break; - } - } - } - } - if (ethereumAddress) { - await setCurrentAddress({ address: ethereumAddress }); - } - return { ethereumAddress, solanaAddress }; - }, - onSuccess: ({ ethereumAddress, solanaAddress }) => { - if (!ethereumAddress || !solanaAddress) { - navigate('/bridge-form'); - } else { - const params = new URLSearchParams({ - outputChain: 'solana', - showReceiverAddressInput: 'on', - receiverAddressInput: solanaAddress, - to: solanaAddress, - }); - navigate(`/bridge-form?${params.toString()}`); - } - }, - }); - - if (isTestnetMode || !wallet || goToBridgeMutation.isLoading || isLoading) { + if (isTestnetMode || !wallet) { return No assets yet; } return ( - - - Empty Wallet Cover - - Fund your wallet - - Buy or transfer crypto to get started - + <> + + + + + Get Started + + By adding crypto to your wallet + + - - - - - {getAddressType(wallet.address) === 'solana' ? ( + - ) : null} + - + + ); } + +export function EmptyPositionsView() { + const { data, isLoading } = useStatsigExperiment(ONRAMP_EXPERIMENT_NAME); + if (isLoading) { + return null; + } + if (data?.group_name?.toLowerCase() === 'test') { + return ; + } else { + return ; + } +} diff --git a/src/ui/pages/Overview/Positions/EmptyPositionsViewLegacy.tsx b/src/ui/pages/Overview/Positions/EmptyPositionsViewLegacy.tsx new file mode 100644 index 0000000000..8df7792d9a --- /dev/null +++ b/src/ui/pages/Overview/Positions/EmptyPositionsViewLegacy.tsx @@ -0,0 +1,133 @@ +import React from 'react'; +import { useMutation, useQuery } from '@tanstack/react-query'; +import { useNavigate } from 'react-router-dom'; +import { normalizeAddress } from 'src/shared/normalizeAddress'; +import { getAddressType } from 'src/shared/wallet/classifiers'; +import { EmptyView } from 'src/ui/components/EmptyView'; +import { usePreferences } from 'src/ui/features/preferences'; +import { walletPort } from 'src/ui/shared/channels'; +import { setCurrentAddress } from 'src/ui/shared/requests/setCurrentAddress'; +import { useWalletParams } from 'src/ui/shared/requests/useWalletParams'; +import { Button } from 'src/ui/ui-kit/Button'; +import { UIText } from 'src/ui/ui-kit/UIText'; +import { UnstyledAnchor } from 'src/ui/ui-kit/UnstyledAnchor'; +import { UnstyledLink } from 'src/ui/ui-kit/UnstyledLink'; +import { VStack } from 'src/ui/ui-kit/VStack'; + +const ZERION_ORIGIN = 'https://app.zerion.io'; + +export function EmptyPositionsViewLegacy() { + const { data: wallet } = useQuery({ + queryKey: ['wallet/uiGetCurrentWallet'], + queryFn: () => { + return walletPort.request('uiGetCurrentWallet'); + }, + }); + + const { data: walletGroups, isLoading } = useQuery({ + queryKey: ['wallet/uiGetWalletGroups'], + queryFn: () => walletPort.request('uiGetWalletGroups'), + useErrorBoundary: true, + suspense: false, + }); + + const { preferences } = usePreferences(); + const addWalletParams = useWalletParams(wallet); + const navigate = useNavigate(); + + const isTestnetMode = preferences?.testnetMode?.on; + + const goToBridgeMutation = useMutation({ + mutationFn: async () => { + const solanaAddress = wallet?.address; + let ethereumAddress: string | null = null; + if (walletGroups) { + for (const group of walletGroups) { + for (const wallet of group.walletContainer.wallets) { + const address = normalizeAddress(wallet.address); + if (getAddressType(address) === 'evm') { + ethereumAddress = address; + break; + } + } + } + } + if (ethereumAddress) { + await setCurrentAddress({ address: ethereumAddress }); + } + return { ethereumAddress, solanaAddress }; + }, + onSuccess: ({ ethereumAddress, solanaAddress }) => { + if (!ethereumAddress || !solanaAddress) { + navigate('/bridge-form'); + } else { + const params = new URLSearchParams({ + outputChain: 'solana', + showReceiverAddressInput: 'on', + receiverAddressInput: solanaAddress, + to: solanaAddress, + }); + navigate(`/bridge-form?${params.toString()}`); + } + }, + }); + + if (isTestnetMode || !wallet || goToBridgeMutation.isLoading || isLoading) { + return No assets yet; + } + + return ( + + + Empty Wallet Cover + + Fund your wallet + + Buy or transfer crypto to get started + + + + + + + {getAddressType(wallet.address) === 'solana' ? ( + + ) : null} + + + ); +} diff --git a/src/ui/pages/Overview/Positions/Positions.tsx b/src/ui/pages/Overview/Positions/Positions.tsx index 8d47d7d6c0..c79c614fa0 100644 --- a/src/ui/pages/Overview/Positions/Positions.tsx +++ b/src/ui/pages/Overview/Positions/Positions.tsx @@ -53,7 +53,6 @@ import { useRenderDelay } from 'src/ui/components/DelayedRender/DelayedRender'; import { minus } from 'src/ui/shared/typography'; import { useAddressPositionsFromNode } from 'src/ui/shared/requests/useAddressPositionsFromNode'; import { CenteredFillViewportView } from 'src/ui/components/FillView/FillView'; -import { EmptyView } from 'src/ui/components/EmptyView'; import { invariant } from 'src/shared/invariant'; import { ErrorBoundary } from 'src/ui/components/ErrorBoundary'; import { useStore } from '@store-unit/react'; @@ -958,7 +957,7 @@ export function Positions({ > {emptyNetworkBalance} - No assets yet + ); diff --git a/src/ui/pages/Receive/AddFundsOptionsDialog.tsx b/src/ui/pages/Receive/AddFundsOptionsDialog.tsx new file mode 100644 index 0000000000..6c92fe167d --- /dev/null +++ b/src/ui/pages/Receive/AddFundsOptionsDialog.tsx @@ -0,0 +1,129 @@ +import React from 'react'; +import type { ExternallyOwnedAccount } from 'src/shared/types/ExternallyOwnedAccount'; +import IdentityIcon from 'jsx:src/ui/assets/identity.svg'; +import QrCodeIcon from 'jsx:src/ui/assets/qr-code.svg'; +import { emitter } from 'src/ui/shared/events'; +import { useWalletParams } from 'src/ui/shared/requests/useWalletParams'; +import { + FrameListItemAnchor, + FrameListItemLink, +} from 'src/ui/ui-kit/FrameList'; +import { Media } from 'src/ui/ui-kit/Media'; +import { BottomSheetDialog } from 'src/ui/ui-kit/ModalDialogs/BottomSheetDialog'; +import { DialogTitle } from 'src/ui/ui-kit/ModalDialogs/DialogTitle'; +import type { HTMLDialogElementInterface } from 'src/ui/ui-kit/ModalDialogs/HTMLDialogElementInterface'; +import { UIText } from 'src/ui/ui-kit/UIText'; +import { VStack } from 'src/ui/ui-kit/VStack'; +import { useOpenAndConnectToZerion } from '../Overview/ActionButtonsRow/ActionButtonsRow'; + +const ZERION_ORIGIN = 'https://app.zerion.io'; + +export function AddFundsOptionsDialog({ + wallet, + dialogRef, + analytics, +}: { + wallet: ExternallyOwnedAccount; + dialogRef: React.RefObject; + analytics: { pathname: string; address: string }; +}) { + const addWalletParams = useWalletParams(wallet); + const buyCryptoHref = `${ZERION_ORIGIN}/deposit?${addWalletParams}`; + const { handleAnchorClick } = useOpenAndConnectToZerion({ + address: wallet.address, + }); + return ( + ( + + Add Funds} /> + + { + handleAnchorClick(event); + emitter.emit('buttonClicked', { + buttonName: 'Buy Crypto', + buttonScope: 'General', + pathname: analytics.pathname, + walletAddress: analytics.address, + }); + }} + target="_blank" + rel="noopener noreferrer" + > + + +
+ } + gap={12} + text={Buy Crypto} + vGap={4} + alignItems="start" + detailText={ + + Use Apple Pay, credit/debit card, or bank transfer to buy + crypto + + } + /> + + { + emitter.emit('buttonClicked', { + buttonName: 'Receive Crypto', + buttonScope: 'General', + pathname: analytics.pathname, + walletAddress: analytics.address, + }); + }} + > + + +
+ } + gap={12} + text={Receive Crypto} + vGap={4} + alignItems="start" + detailText={ + + Transfer crypto from another wallet or exchange with QR code + or wallet address + + } + /> + + + + )} + /> + ); +} diff --git a/src/ui/pages/Receive/AddressDetails.tsx b/src/ui/pages/Receive/AddressDetails.tsx index 2b415ce06f..8eb364e52e 100644 --- a/src/ui/pages/Receive/AddressDetails.tsx +++ b/src/ui/pages/Receive/AddressDetails.tsx @@ -1,13 +1,200 @@ -import React from 'react'; +import React, { useMemo, useRef } from 'react'; import { QRCode } from 'react-qrcode-logo'; import { Button } from 'src/ui/ui-kit/Button'; import { HStack } from 'src/ui/ui-kit/HStack'; -import { Spacer } from 'src/ui/ui-kit/Spacer'; import { UIText } from 'src/ui/ui-kit/UIText'; import { VStack } from 'src/ui/ui-kit/VStack'; import CopyIcon from 'jsx:src/ui/assets/copy.svg'; import CheckIcon from 'jsx:src/ui/assets/check_double.svg'; import { useCopyToClipboard } from 'src/ui/shared/useCopyToClipboard'; +import { UnstyledButton } from 'src/ui/ui-kit/UnstyledButton'; +import { BottomSheetDialog } from 'src/ui/ui-kit/ModalDialogs/BottomSheetDialog'; +import { DialogTitle } from 'src/ui/ui-kit/ModalDialogs/DialogTitle'; +import type { HTMLDialogElementInterface } from 'src/ui/ui-kit/ModalDialogs/HTMLDialogElementInterface'; +import EcosystemSolanaIcon from 'jsx:src/ui/assets/ecosystem-solana.svg'; +import EcosystemEthereumIcon from 'jsx:src/ui/assets/ecosystem-ethereum.svg'; +import { useNetworks } from 'src/modules/networks/useNetworks'; +import { PageStickyFooter } from 'src/ui/components/PageStickyFooter'; +import { isCustomNetworkId } from 'src/modules/ethereum/chains/helpers'; +import { NetworkIcon } from 'src/ui/components/NetworkIcon'; +import { + getAddressType, + type BlockchainType, +} from 'src/shared/wallet/classifiers'; + +function NetworkList({ standard }: { standard: BlockchainType }) { + const { networks } = useNetworks(); + const allNetworks = useMemo(() => { + return networks + ?.getDefaultNetworks(standard) + .filter((item) => !item.is_testnet && !isCustomNetworkId(item.id)); + }, [networks]); + + return ( + + {allNetworks?.map((network) => ( + + + {network.name} + + ))} + + ); +} + +function EthereumNetworksVisualStack() { + return ( +
+ + + + + +
+ ); +} + +function SupportedNetworks({ address }: { address: string }) { + const dialogRef = useRef(null); + const standard = getAddressType(address); + + return ( + <> + + {standard === 'solana' ? ( + + ) : ( + + + + +60 more + + + )} + { + dialogRef.current?.showModal(); + }} + > + Supported Networks + + + ( + <> + + Supported Networks} + /> + + These are the blockchains Zerion supports for sending, + receiving, and managing assets. + + + {standard === 'solana' ? ( + <> + + + To use the Ethereum ecosystem, choose an Ethereum wallet. + + + ) : ( + <> + + + To use the Solana ecosystem, choose a Solana wallet. + + + )} + + + + + + + + )} + /> + + ); +} export function AddressDetails({ address, @@ -19,7 +206,7 @@ export function AddressDetails({ const { handleCopy, isSuccess } = useCopyToClipboard({ text: address }); return ( - +
+ - {domain ? ( - {domain} - ) : ( - - )} + {domain ? {domain} : null} {address.slice(0, 6)} {address.slice(6, -4)} diff --git a/src/ui/pages/Receive/Receive.tsx b/src/ui/pages/Receive/Receive.tsx index 7560d75a77..a32f06685d 100644 --- a/src/ui/pages/Receive/Receive.tsx +++ b/src/ui/pages/Receive/Receive.tsx @@ -3,8 +3,6 @@ import { useSearchParams } from 'react-router-dom'; import { Background } from 'src/ui/components/Background'; import { NavigationTitle } from 'src/ui/components/NavigationTitle'; import { PageColumn } from 'src/ui/components/PageColumn'; -import { UIText } from 'src/ui/ui-kit/UIText'; -import { VStack } from 'src/ui/ui-kit/VStack'; import { invariant } from 'src/shared/invariant'; import { useQuery } from '@tanstack/react-query'; import { lookupAddressName } from 'src/modules/name-service'; @@ -34,30 +32,13 @@ export function Receive() {
} /> - -
- - Assets can only be sent within -
- the same network -
-
- -
+ );