diff --git a/packages/app/public/images/gray_square_background.svg b/packages/app/public/images/gray_square_background.svg index 4cc524c4c..ef21f98b8 100644 --- a/packages/app/public/images/gray_square_background.svg +++ b/packages/app/public/images/gray_square_background.svg @@ -2,7 +2,7 @@ - + diff --git a/packages/app/public/images/onramp/alchemy_pay.webp b/packages/app/public/images/onramp/alchemy_pay.webp new file mode 100644 index 000000000..f472d41fd Binary files /dev/null and b/packages/app/public/images/onramp/alchemy_pay.webp differ diff --git a/packages/app/public/images/onramp/banxa.webp b/packages/app/public/images/onramp/banxa.webp new file mode 100644 index 000000000..817ca4ef1 Binary files /dev/null and b/packages/app/public/images/onramp/banxa.webp differ diff --git a/packages/app/public/images/onramp/coinbase.webp b/packages/app/public/images/onramp/coinbase.webp new file mode 100644 index 000000000..58d055533 Binary files /dev/null and b/packages/app/public/images/onramp/coinbase.webp differ diff --git a/packages/app/public/images/onramp/kado.webp b/packages/app/public/images/onramp/kado.webp new file mode 100644 index 000000000..520b87e67 Binary files /dev/null and b/packages/app/public/images/onramp/kado.webp differ diff --git a/packages/app/public/images/onramp/mt_pelerin.webp b/packages/app/public/images/onramp/mt_pelerin.webp new file mode 100644 index 000000000..3d5a8c04d Binary files /dev/null and b/packages/app/public/images/onramp/mt_pelerin.webp differ diff --git a/packages/app/public/images/onramp/onramp.webp b/packages/app/public/images/onramp/onramp.webp new file mode 100644 index 000000000..2444befaf Binary files /dev/null and b/packages/app/public/images/onramp/onramp.webp differ diff --git a/packages/app/public/images/onramp/ramp.webp b/packages/app/public/images/onramp/ramp.webp new file mode 100644 index 000000000..6dd99239f Binary files /dev/null and b/packages/app/public/images/onramp/ramp.webp differ diff --git a/packages/app/public/images/onramp/simplex.webp b/packages/app/public/images/onramp/simplex.webp new file mode 100644 index 000000000..794e69b92 Binary files /dev/null and b/packages/app/public/images/onramp/simplex.webp differ diff --git a/packages/app/public/images/onramp/transak.webp b/packages/app/public/images/onramp/transak.webp new file mode 100644 index 000000000..e1338e98b Binary files /dev/null and b/packages/app/public/images/onramp/transak.webp differ diff --git a/packages/app/src/app/(embed)/bridge/embed/EmbedPageWrapper.tsx b/packages/app/src/app/(embed)/bridge/embed/EmbedPageWrapper.tsx index 23c5c8604..b74311026 100644 --- a/packages/app/src/app/(embed)/bridge/embed/EmbedPageWrapper.tsx +++ b/packages/app/src/app/(embed)/bridge/embed/EmbedPageWrapper.tsx @@ -4,7 +4,7 @@ import BridgeClient from '../../../(with-sidebar)/bridge/BridgeClient'; import { BridgePageProps, initializeBridgePage } from '../../../../utils/bridgePageUtils'; export default async function EmbedPageWrapper({ searchParams, redirectPath }: BridgePageProps) { - await initializeBridgePage(searchParams, redirectPath); + await initializeBridgePage({ searchParams, redirectPath }); return ( <> diff --git a/packages/app/src/app/(embed)/bridge/embed/buy/[slug]/page.tsx b/packages/app/src/app/(embed)/bridge/embed/buy/[slug]/page.tsx new file mode 100644 index 000000000..ceb4cce63 --- /dev/null +++ b/packages/app/src/app/(embed)/bridge/embed/buy/[slug]/page.tsx @@ -0,0 +1,19 @@ +import { Slug } from 'packages/app/src/utils/bridgePageUtils'; + +import { PathnameEnum } from '@/bridge/constants'; + +import EmbedPageWrapper from '../../EmbedPageWrapper'; + +type Props = { + searchParams: { [key: string]: string | string[] | undefined }; + params: { slug: Slug }; +}; + +export default async function EmbeddedBuyOnrampServicePage({ searchParams, params }: Props) { + return ( + + ); +} diff --git a/packages/app/src/app/(with-sidebar)/bridge/BridgePageWrapper.tsx b/packages/app/src/app/(with-sidebar)/bridge/BridgePageWrapper.tsx index 42f94f1c3..5e7c7ec41 100644 --- a/packages/app/src/app/(with-sidebar)/bridge/BridgePageWrapper.tsx +++ b/packages/app/src/app/(with-sidebar)/bridge/BridgePageWrapper.tsx @@ -2,7 +2,7 @@ import { BridgePageProps, initializeBridgePage } from '../../../utils/bridgePage import BridgeClient from './BridgeClient'; export default async function BridgePageWrapper({ searchParams, redirectPath }: BridgePageProps) { - await initializeBridgePage(searchParams, redirectPath); + await initializeBridgePage({ searchParams, redirectPath }); return (
diff --git a/packages/app/src/app/(with-sidebar)/bridge/buy/[slug]/page.tsx b/packages/app/src/app/(with-sidebar)/bridge/buy/[slug]/page.tsx new file mode 100644 index 000000000..3afcd041e --- /dev/null +++ b/packages/app/src/app/(with-sidebar)/bridge/buy/[slug]/page.tsx @@ -0,0 +1,26 @@ +import type { Metadata } from 'next'; +import { Slug } from 'packages/app/src/utils/bridgePageUtils'; + +import { PathnameEnum } from '@/bridge/constants'; + +import BridgePageWrapper from '../../BridgePageWrapper'; + +type Props = { + searchParams: { [key: string]: string | string[] | undefined }; + params: { slug: Slug }; +}; + +export const metadata: Metadata = { + title: 'On-Ramp to Arbitrum', + description: + "On-ramp directly to Arbitrum with one of several third party providers. Built to scale Ethereum, Arbitrum brings you 10x lower costs while inheriting Ethereum's security model. Arbitrum is a Layer 2 Optimistic Rollup.", +}; + +export default async function BridgeBuyOnrampServicePage({ searchParams, params }: Props) { + return ( + + ); +} diff --git a/packages/app/src/utils/bridgePageUtils.tsx b/packages/app/src/utils/bridgePageUtils.tsx index 227907905..0ea49527c 100644 --- a/packages/app/src/utils/bridgePageUtils.tsx +++ b/packages/app/src/utils/bridgePageUtils.tsx @@ -1,17 +1,17 @@ +import { onrampServices } from '@/bridge/components/BuyPanel/utils'; import { PathnameEnum } from '@/bridge/constants'; import { addOrbitChainsToArbitrumSDK } from '../initialization'; import { sanitizeAndRedirect } from './sanitizeAndRedirect'; +export type Slug = (typeof onrampServices)[number]['slug']; + export interface BridgePageProps { searchParams: { [key: string]: string | string[] | undefined }; - redirectPath: PathnameEnum; + redirectPath: PathnameEnum | `${PathnameEnum.BUY}/${Slug}` | `${PathnameEnum.EMBED_BUY}/${Slug}`; } -export async function initializeBridgePage( - searchParams: { [key: string]: string | string[] | undefined }, - redirectPath: PathnameEnum, -) { +export async function initializeBridgePage({ searchParams, redirectPath }: BridgePageProps) { /** * This code is run on every query param change, * we don't want to sanitize every query param change. diff --git a/packages/app/tailwind.config.js b/packages/app/tailwind.config.js index 96734fdeb..68a654bec 100644 --- a/packages/app/tailwind.config.js +++ b/packages/app/tailwind.config.js @@ -19,7 +19,6 @@ module.exports = { gradientCelebration: 'linear-gradient(to right, #1B4ADD6F, #E573106F)', highlight: 'linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 25%, rgba(255, 255, 255, 0.1) 75%, rgba(255, 255, 255, 0))', - eclipse: 'radial-gradient(ellipse 550px 200px at center, #262626 70%, transparent 70%)', }, colors: { // ACTION diff --git a/packages/arb-token-bridge-ui/src/components/BuyPanel/BackButton.tsx b/packages/arb-token-bridge-ui/src/components/BuyPanel/BackButton.tsx new file mode 100644 index 000000000..03898dbbe --- /dev/null +++ b/packages/arb-token-bridge-ui/src/components/BuyPanel/BackButton.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { ChevronLeftIcon } from '@heroicons/react/24/outline'; +import Link from 'next/link'; +import { useSearchParams } from 'next/navigation'; + +import { PathnameEnum } from '@/bridge/constants'; +import { useMode } from '@/bridge/hooks/useMode'; + +import { Button } from '../common/Button'; + +export function BackButton() { + const { embedMode } = useMode(); + const searchParams = useSearchParams(); + + return ( + + + Back + + ); +} diff --git a/packages/arb-token-bridge-ui/src/components/BuyPanel.tsx b/packages/arb-token-bridge-ui/src/components/BuyPanel/BuyPanel.tsx similarity index 58% rename from packages/arb-token-bridge-ui/src/components/BuyPanel.tsx rename to packages/arb-token-bridge-ui/src/components/BuyPanel/BuyPanel.tsx index 1b28764de..8bd5af66e 100644 --- a/packages/arb-token-bridge-ui/src/components/BuyPanel.tsx +++ b/packages/arb-token-bridge-ui/src/components/BuyPanel/BuyPanel.tsx @@ -1,7 +1,9 @@ import { ChevronDownIcon } from '@heroicons/react/24/outline'; +import { ExclamationCircleIcon } from '@heroicons/react/24/solid'; import { BigNumber, utils } from 'ethers'; import dynamic from 'next/dynamic'; -import React, { PropsWithChildren, memo, useCallback } from 'react'; +import { usePathname } from 'next/navigation'; +import React, { PropsWithChildren, memo, useMemo } from 'react'; import { twMerge } from 'tailwind-merge'; import { Chain } from 'viem'; import { useAccount, useBalance } from 'wagmi'; @@ -10,69 +12,26 @@ import { shallow } from 'zustand/shallow'; import { getProviderForChainId } from '@/token-bridge-sdk/utils'; -import { useETHPrice } from '../hooks/useETHPrice'; -import { useMode } from '../hooks/useMode'; -import { useNativeCurrency } from '../hooks/useNativeCurrency'; -import { ChainId } from '../types/ChainId'; -import { getAPIBaseUrl } from '../util'; -import { formatAmount, formatUSD } from '../util/NumberUtils'; -import { isOnrampEnabled, isOnrampServiceEnabled } from '../util/featureFlag'; -import { getNetworkName } from '../util/networks'; -import { TokenLogoFallback } from './TransferPanel/TokenInfo'; -import { Button } from './common/Button'; -import { Dialog } from './common/Dialog'; -import { DialogProps, DialogWrapper, useDialog2 } from './common/Dialog2'; -import { NetworkImage } from './common/NetworkImage'; -import { NetworksPanel } from './common/NetworkSelectionContainer'; -import { SafeImage } from './common/SafeImage'; -import { SearchPanel } from './common/SearchPanel/SearchPanel'; -import { Loader } from './common/atoms/Loader'; - -function MoonPaySkeleton({ children }: PropsWithChildren) { - const { embedMode } = useMode(); - - return ( -
-
-
-
- } - /> -

MoonPay

-

- PayPal, Debit Card, Apple Pay -

-
-
div]:!m-0 [&>div]:!w-full [&>div]:!border-x-0 [&>div]:!border-none [&>div]:!p-0 sm:[&>div]:!rounded sm:[&>div]:!border-x', - '[&_iframe]:rounded-xl', - )} - > - {children} -
-

- On-Ramps are not directly endorsed by Arbitrum. Please use at your own risk. -

-
- ); -} +import { useETHPrice } from '../../hooks/useETHPrice'; +import { useMode } from '../../hooks/useMode'; +import { useNativeCurrency } from '../../hooks/useNativeCurrency'; +import { ChainId } from '../../types/ChainId'; +import { formatAmount, formatUSD } from '../../util/NumberUtils'; +import { isOnrampEnabled, isOnrampServiceEnabled } from '../../util/featureFlag'; +import { getNetworkName } from '../../util/networks'; +import { TokenLogoFallback } from '../TransferPanel/TokenInfo'; +import { Button } from '../common/Button'; +import { Dialog } from '../common/Dialog'; +import { DialogProps, DialogWrapper, useDialog2 } from '../common/Dialog2'; +import { NetworkImage } from '../common/NetworkImage'; +import { NetworksPanel } from '../common/NetworkSelectionContainer'; +import { SafeImage } from '../common/SafeImage'; +import { SearchPanel } from '../common/SearchPanel/SearchPanel'; +import { Loader } from '../common/atoms/Loader'; +import { Homepage } from './Homepage'; +import { LinkoutOnrampPanel } from './LinkoutOnrampPanel'; +import { MoonPayPanel, MoonPaySkeleton } from './MoonPayPanel'; +import { onrampServices } from './utils'; const MoonPayProvider = dynamic( () => import('@moonpay/moonpay-react').then((mod) => mod.MoonPayProvider), @@ -179,7 +138,6 @@ function BuyPanelNetworkButton({ ); } -/* eslint-disable @typescript-eslint/no-unused-vars */ const BalanceWrapper = memo(function BalanceWrapper() { const { address, isConnected } = useAccount(); const { ethToUSD } = useETHPrice(); @@ -192,6 +150,13 @@ const BalanceWrapper = memo(function BalanceWrapper() { error: balanceError, } = useBalance({ chainId: selectedChainId, address }); const showPriceInUsd = nativeCurrency.symbol.toLowerCase() === 'eth'; + const balanceInUsd = useMemo(() => { + if (!balanceState || !showPriceInUsd) { + return null; + } + return ethToUSD(Number(utils.formatEther(BigNumber.from(balanceState.value)))); + }, [balanceState, ethToUSD, showPriceInUsd]); + const isBalanceLessThan15Usd = Number(balanceInUsd) < 15; const [dialogProps, openDialog] = useDialog2(); const openBuyPanelNetworkSelectionDialog = () => { openDialog('buy_panel_network_selection'); @@ -228,58 +193,52 @@ const BalanceWrapper = memo(function BalanceWrapper() { {!isLoadingBalance && (balanceError || typeof balanceState === 'undefined') && ( Failed to load balance. )} - {balanceState && showPriceInUsd && ( - - ({formatUSD(ethToUSD(Number(utils.formatEther(BigNumber.from(balanceState.value)))))}) + {balanceInUsd !== null && balanceInUsd !== 0 && ( + + {balanceInUsd} {formatUSD(balanceInUsd)} )}

+ {isBalanceLessThan15Usd && ( +

+ + Low wallet balance +

+ )} + ); }); -const MoonPayPanel = memo(function MoonPayPanel() { - const { address } = useAccount(); - const showMoonPay = isOnrampServiceEnabled('moonpay'); - - const handleGetSignature = useCallback(async (widgetUrl: string): Promise => { - const response = await fetch(`${getAPIBaseUrl()}/api/moonpay`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ url: widgetUrl }), - }); - const { signature } = await response.json(); - return signature; - }, []); - - if (!showMoonPay) { - return null; - } - - const MoonPayBuyWidget = dynamic( - () => import('@moonpay/moonpay-react').then((mod) => mod.MoonPayBuyWidget), - { - ssr: false, - }, - ); +function OnrampDisclaimer() { + const { embedMode } = useMode(); return ( - - - +

+ On-Ramps are not endorsed by Arbitrum. Please use at your own risk. +

); -}); +} + +function OnrampServicePanel() { + const pathname = usePathname(); + const onrampService = pathname.split('/').pop(); + const allOnrampServices = onrampServices.map((service) => service.slug); + + switch (onrampService) { + case 'moonpay': + if (!isMoonPayEnabled) { + return null; + } + return ; + case allOnrampServices.find((service) => service === onrampService): + return ; + default: + return ; + } +} export function BuyPanel() { const { embedMode } = useMode(); @@ -287,13 +246,17 @@ export function BuyPanel() { return (
+ + - + + +
); } diff --git a/packages/arb-token-bridge-ui/src/components/BuyPanel/Homepage.tsx b/packages/arb-token-bridge-ui/src/components/BuyPanel/Homepage.tsx new file mode 100644 index 000000000..7c59fe488 --- /dev/null +++ b/packages/arb-token-bridge-ui/src/components/BuyPanel/Homepage.tsx @@ -0,0 +1,100 @@ +import { ArrowUpRightIcon } from '@heroicons/react/24/outline'; +import Image from 'next/image'; +import Link from 'next/link'; +import { usePathname, useRouter, useSearchParams } from 'next/navigation'; +import { useCallback } from 'react'; +import { twMerge } from 'tailwind-merge'; + +import { trackEvent } from '@/bridge/util/AnalyticsUtils'; +import MoonPay from '@/images/onramp/moonpay.svg'; + +import { Button } from '../common/Button'; +import { onrampServices } from './utils'; + +function OnrampServiceTile({ name, logo, slug }: { name: string; logo: string; slug: string }) { + const pathname = usePathname(); + const searchParams = useSearchParams(); + + return ( + { + trackEvent('Onramp Service Click', { service: name }); + }} + > + + + ); +} + +function MoonPayTile() { + const pathname = usePathname(); + const searchParams = useSearchParams(); + + return ( + { + trackEvent('Onramp Service Click', { service: 'MoonPay' }); + }} + > + + + ); +} + +export function Homepage() { + const router = useRouter(); + + const allOnrampOnClick = useCallback(() => { + router.push('/projects?subcategories=fiat-on-ramp'); + }, [router]); + + return ( +
+ + {onrampServices.map((service) => ( + + ))} + +
+ ); +} diff --git a/packages/arb-token-bridge-ui/src/components/BuyPanel/LinkoutOnrampPanel.tsx b/packages/arb-token-bridge-ui/src/components/BuyPanel/LinkoutOnrampPanel.tsx new file mode 100644 index 000000000..d3da86cf6 --- /dev/null +++ b/packages/arb-token-bridge-ui/src/components/BuyPanel/LinkoutOnrampPanel.tsx @@ -0,0 +1,54 @@ +import { ArrowUpRightIcon } from '@heroicons/react/24/outline'; +import Image from 'next/image'; +import { twMerge } from 'tailwind-merge'; + +import { useMode } from '@/bridge/hooks/useMode'; + +import { Button } from '../common/Button'; +import { ExternalLink } from '../common/ExternalLink'; +import { BackButton } from './BackButton'; +import { onrampServices } from './utils'; + +export function LinkoutOnrampPanel({ serviceSlug }: { serviceSlug: string }) { + const { embedMode } = useMode(); + const service = onrampServices.find((s) => s.slug === serviceSlug); + + if (!service) { + return null; + } + + return ( +
+
+
+ {service.name} +
+
+

{service.name}

+

+ Buy and transfer instantly using your debit card, bank account with Thirdweb{' '} + {service.name}. +

+
+
+ + + + +
+ ); +} diff --git a/packages/arb-token-bridge-ui/src/components/BuyPanel/MoonPayPanel.tsx b/packages/arb-token-bridge-ui/src/components/BuyPanel/MoonPayPanel.tsx new file mode 100644 index 000000000..a31c68c23 --- /dev/null +++ b/packages/arb-token-bridge-ui/src/components/BuyPanel/MoonPayPanel.tsx @@ -0,0 +1,90 @@ +import dynamic from 'next/dynamic'; +import { PropsWithChildren, memo, useCallback } from 'react'; +import { twMerge } from 'tailwind-merge'; +import { useAccount } from 'wagmi'; + +import { useMode } from '@/bridge/hooks/useMode'; + +import { getAPIBaseUrl } from '../../util'; +import { isOnrampServiceEnabled } from '../../util/featureFlag'; +import { SafeImage } from '../common/SafeImage'; +import { BackButton } from './BackButton'; + +export function MoonPaySkeleton({ children }: PropsWithChildren) { + const { embedMode } = useMode(); + + return ( +
+
+
+ } + /> +

MoonPay

+

+ PayPal, Debit Card, Apple Pay +

+
+
div]:!m-0 [&>div]:!w-full [&>div]:!border-x-0 [&>div]:!border-none [&>div]:!p-0 sm:[&>div]:!rounded sm:[&>div]:!border-x', + '[&_iframe]:rounded-xl', + )} + > + {children} +
+ +
+ ); +} + +export const MoonPayPanel = memo(function MoonPayPanel() { + const { address } = useAccount(); + const showMoonPay = isOnrampServiceEnabled('moonpay'); + + const handleGetSignature = useCallback(async (widgetUrl: string): Promise => { + const response = await fetch(`${getAPIBaseUrl()}/api/moonpay`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ url: widgetUrl }), + }); + const { signature } = await response.json(); + return signature; + }, []); + + if (!showMoonPay) { + return null; + } + + const MoonPayBuyWidget = dynamic( + () => import('@moonpay/moonpay-react').then((mod) => mod.MoonPayBuyWidget), + { + ssr: false, + }, + ); + + return ( + + + + ); +}); diff --git a/packages/arb-token-bridge-ui/src/components/BuyPanel/utils.ts b/packages/arb-token-bridge-ui/src/components/BuyPanel/utils.ts new file mode 100644 index 000000000..a50d538eb --- /dev/null +++ b/packages/arb-token-bridge-ui/src/components/BuyPanel/utils.ts @@ -0,0 +1,67 @@ +import { ChainId } from '@/bridge/types/ChainId'; + +export const onrampServices = [ + { + name: 'Transak', + slug: 'transak', + logo: '/images/onramp/transak.webp', + link: 'https://global.transak.com', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, + { + name: 'Ramp', + slug: 'ramp', + logo: '/images/onramp/ramp.webp', + link: 'https://ramp.network/buy', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, + { + name: 'Mt Pelerin', + slug: 'mt-pelerin', + logo: '/images/onramp/mt_pelerin.webp', + link: 'https://www.mtpelerin.com/buy-crypto', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, + { + name: 'Coinbase Pay', + slug: 'coinbase-pay', + logo: '/images/onramp/coinbase.webp', + link: 'https://login.coinbase.com/signin?client_id=258660e1-9cfe-4202-9eda-d3beedb3e118&oauth_challenge=851bae2a-c907-413d-9a12-71c1dfaa5d4f', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, + { + name: 'Onramp', + slug: 'onramp', + logo: '/images/onramp/onramp.webp', + link: 'https://onramp.money', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, + { + name: 'Banxa', + slug: 'banxa', + logo: '/images/onramp/banxa.webp', + link: 'https://checkout.banxa.com', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, + { + name: 'Simplex', + slug: 'simplex', + logo: '/images/onramp/simplex.webp', + link: 'https://buy.simplex.com', + chains: [ChainId.Ethereum], + }, + { + name: 'Kado', + slug: 'kado', + logo: '/images/onramp/kado.webp', + link: 'https://swapped.com/', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, + { + name: 'Alchemy Pay', + slug: 'alchemy-pay', + logo: '/images/onramp/alchemy_pay.webp', + link: 'https://ramp.alchemypay.org/#/index', + chains: [ChainId.Ethereum, ChainId.ArbitrumOne], + }, +] as const; diff --git a/packages/arb-token-bridge-ui/src/components/MainContent/MainContent.tsx b/packages/arb-token-bridge-ui/src/components/MainContent/MainContent.tsx index 9db18eaaf..c27f95b2f 100644 --- a/packages/arb-token-bridge-ui/src/components/MainContent/MainContent.tsx +++ b/packages/arb-token-bridge-ui/src/components/MainContent/MainContent.tsx @@ -3,12 +3,12 @@ import { useLocalStorage } from '@uidotdev/usehooks'; import { usePathname } from 'next/navigation'; import { Fragment, useMemo } from 'react'; -import { PathnameEnum } from '@/bridge/constants'; +import { isBridgeBuyOrSubpages } from '@/bridge/util/pathnameUtils'; import { isOnrampFeatureEnabled } from '@/bridge/util/queryParamUtils'; import { useArbQueryParams } from '../../hooks/useArbQueryParams'; import { useMode } from '../../hooks/useMode'; -import { BuyPanel } from '../BuyPanel'; +import { BuyPanel } from '../BuyPanel/BuyPanel'; import { RecoverFunds } from '../RecoverFunds'; import { TopNavBar } from '../TopNavBar'; import { TransactionHistory } from '../TransactionHistory/TransactionHistory'; @@ -28,7 +28,7 @@ export function MainContent() { // `tab` from useArbQueryParams will never be 0 when showBuyPanel is true // because we use /buy and don't use ?tab=buy // so we need to hardcode to return 0 rather than `tab` - if (pathname === PathnameEnum.BUY) { + if (isBridgeBuyOrSubpages(pathname)) { return 0; } return tab; @@ -52,7 +52,7 @@ export function MainContent() { {}}> - + {showBuyPanel && ( diff --git a/packages/arb-token-bridge-ui/src/components/TopNavBar.tsx b/packages/arb-token-bridge-ui/src/components/TopNavBar.tsx index 854669f6f..b29daff18 100644 --- a/packages/arb-token-bridge-ui/src/components/TopNavBar.tsx +++ b/packages/arb-token-bridge-ui/src/components/TopNavBar.tsx @@ -9,6 +9,7 @@ import { twMerge } from 'tailwind-merge'; import { PathnameEnum } from '../constants'; import { useArbQueryParams } from '../hooks/useArbQueryParams'; import { useMode } from '../hooks/useMode'; +import { isBridgeBuyOrSubpages } from '../util/pathnameUtils'; import { TabParamEnum, isOnrampFeatureEnabled } from '../util/queryParamUtils'; import { useTransactionReminderInfo } from './TransactionHistory/useTransactionReminderInfo'; @@ -24,7 +25,7 @@ function StyledTab({ hrefQuery?: string; }>) { const pathname = usePathname(); - const isBuyTab = pathname === PathnameEnum.BUY; + const isBuyTab = isBridgeBuyOrSubpages(pathname); const { embedMode } = useMode(); return ( @@ -56,7 +57,7 @@ export function TopNavBar() { const showBuyPanel = isOnrampFeatureEnabled({ disabledFeatures }); const { embedMode } = useMode(); const pathname = usePathname(); - const isBuyTab = pathname === PathnameEnum.BUY; + const isBuyTab = isBridgeBuyOrSubpages(pathname); const searchParams = useSearchParams(); const searchParamsWithoutTab = useMemo(() => { diff --git a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx index 1f990f0df..957ac1705 100644 --- a/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx +++ b/packages/arb-token-bridge-ui/src/components/TransferPanel/TransferPanel.tsx @@ -19,10 +19,11 @@ import { useTransactionHistory } from '@/bridge/hooks/useTransactionHistory'; import { BridgeTransfer, TransferOverrides } from '@/bridge/token-bridge-sdk/BridgeTransferStarter'; import { BridgeTransferStarterFactory } from '@/bridge/token-bridge-sdk/BridgeTransferStarterFactory'; import { CctpTransferStarter } from '@/bridge/token-bridge-sdk/CctpTransferStarter'; +import { isEmbeddedBridgeBuyOrSubpages } from '@/bridge/util/pathnameUtils'; import { LifiTransferStarter } from '@/token-bridge-sdk/LifiTransferStarter'; import { getTokenOverride } from '../../app/api/crosschain-transfers/utils'; -import { DOCS_DOMAIN, GET_HELP_LINK, PathnameEnum } from '../../constants'; +import { DOCS_DOMAIN, GET_HELP_LINK } from '../../constants'; import { useIsBatchTransferSupported } from '../../hooks/TransferPanel/useIsBatchTransferSupported'; import { useSetInputAmount } from '../../hooks/TransferPanel/useSetInputAmount'; import { useAccountType } from '../../hooks/useAccountType'; @@ -1259,7 +1260,7 @@ export function TransferPanel() { }; if (embedMode) { - if (pathname === PathnameEnum.EMBED_BUY && showBuyPanel) { + if (isEmbeddedBridgeBuyOrSubpages(pathname) && showBuyPanel) { return ; } diff --git a/packages/arb-token-bridge-ui/src/components/Widget/WidgetBuyPanel.tsx b/packages/arb-token-bridge-ui/src/components/Widget/WidgetBuyPanel.tsx index a51e4ef95..9426afb7a 100644 --- a/packages/arb-token-bridge-ui/src/components/Widget/WidgetBuyPanel.tsx +++ b/packages/arb-token-bridge-ui/src/components/Widget/WidgetBuyPanel.tsx @@ -1,6 +1,6 @@ import { twMerge } from 'tailwind-merge'; -import { BuyPanel } from '../BuyPanel'; +import { BuyPanel } from '../BuyPanel/BuyPanel'; import { DialogProps, DialogWrapper, OpenDialogFunction } from '../common/Dialog2'; import { WidgetHeaderRow } from './WidgetHeaderRow'; diff --git a/packages/arb-token-bridge-ui/src/components/Widget/WidgetModeDropdown.tsx b/packages/arb-token-bridge-ui/src/components/Widget/WidgetModeDropdown.tsx index d5a40e29f..28d805f2c 100644 --- a/packages/arb-token-bridge-ui/src/components/Widget/WidgetModeDropdown.tsx +++ b/packages/arb-token-bridge-ui/src/components/Widget/WidgetModeDropdown.tsx @@ -13,6 +13,7 @@ import { useSearchParams } from 'next/navigation'; import { twMerge } from 'tailwind-merge'; import { PathnameEnum } from '@/bridge/constants'; +import { isEmbeddedBridgeBuyOrSubpages } from '@/bridge/util/pathnameUtils'; import { useArbQueryParams } from '../../hooks/useArbQueryParams'; import { isOnrampFeatureEnabled } from '../../util/queryParamUtils'; @@ -45,7 +46,7 @@ export const WidgetModeDropdown = () => { const router = useRouter(); const searchParams = useSearchParams(); const pathname = usePathname(); - const isBuyTab = pathname === PathnameEnum.EMBED_BUY; + const isBuyTab = isEmbeddedBridgeBuyOrSubpages(pathname); const isBridgeTab = pathname === PathnameEnum.EMBED; const [{ disabledFeatures }] = useArbQueryParams(); diff --git a/packages/arb-token-bridge-ui/src/components/common/Button.tsx b/packages/arb-token-bridge-ui/src/components/common/Button.tsx index e040b84d0..2734b700e 100644 --- a/packages/arb-token-bridge-ui/src/components/common/Button.tsx +++ b/packages/arb-token-bridge-ui/src/components/common/Button.tsx @@ -1,4 +1,4 @@ -import { ArrowRightIcon } from '@heroicons/react/24/outline'; +import { ChevronRightIcon } from '@heroicons/react/24/outline'; import React, { forwardRef, useState } from 'react'; import { twMerge } from 'tailwind-merge'; @@ -74,9 +74,9 @@ export const Button = forwardRef( {children} {props.showArrow && ( -