Skip to content

Commit

Permalink
fix: dynamic crypto providers (#1248)
Browse files Browse the repository at this point in the history
* dynamic crypto providers

* fixed typo
  • Loading branch information
brendan-defi authored Nov 13, 2024
1 parent d11bf62 commit 0c7febf
Show file tree
Hide file tree
Showing 9 changed files with 165 additions and 100 deletions.
5 changes: 4 additions & 1 deletion apps/web/app/(base-org)/builder-anniversary-nft/page.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import CryptoProviders from 'apps/web/app/CryptoProviders';
import { BuilderNftHero } from 'apps/web/src/components/BuilderNft/BuilderNftHero';
import type { Metadata } from 'next';

Expand All @@ -13,7 +14,9 @@ export const metadata: Metadata = {
export default async function About() {
return (
<main className="flex w-full flex-col items-center bg-black">
<BuilderNftHero />
<CryptoProviders>
<BuilderNftHero />
</CryptoProviders>
</main>
);
}
11 changes: 7 additions & 4 deletions apps/web/app/(basenames)/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import CryptoProviders from 'apps/web/app/CryptoProviders';
import ErrorsProvider from 'apps/web/contexts/Errors';
import UsernameNav from 'apps/web/src/components/Layout/UsernameNav';

Expand Down Expand Up @@ -27,10 +28,12 @@ export default async function BasenameLayout({
}) {
return (
<ErrorsProvider context="basenames">
<div className="max-w-screen flex min-h-screen flex-col">
<UsernameNav />
{children}
</div>
<CryptoProviders>
<div className="max-w-screen flex min-h-screen flex-col">
<UsernameNav />
{children}
</div>
</CryptoProviders>
</ErrorsProvider>
);
}
87 changes: 8 additions & 79 deletions apps/web/app/AppProviders.tsx
Original file line number Diff line number Diff line change
@@ -1,35 +1,19 @@
'use client';
import '@rainbow-me/rainbowkit/styles.css';
import '@coinbase/onchainkit/styles.css';

import {
Provider as CookieManagerProvider,
Region,
TrackingCategory,
TrackingPreference,
} from '@coinbase/cookie-manager';
import { AppConfig, OnchainKitProvider } from '@coinbase/onchainkit';
import { Provider as TooltipProvider } from '@radix-ui/react-tooltip';
import { connectorsForWallets, RainbowKitProvider } from '@rainbow-me/rainbowkit';
import {
coinbaseWallet,
metaMaskWallet,
phantomWallet,
rainbowWallet,
uniswapWallet,
walletConnectWallet,
} from '@rainbow-me/rainbowkit/wallets';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import ExperimentsProvider from 'base-ui/contexts/Experiments';
import useSprig from 'base-ui/hooks/useSprig';
import { useCallback, useRef } from 'react';
import { createConfig, http, WagmiProvider } from 'wagmi';
import { base, baseSepolia, mainnet } from 'wagmi/chains';
import { cookieManagerConfig } from '../src/utils/cookieManagerConfig';
import ClientAnalyticsScript from 'apps/web/src/components/ClientAnalyticsScript/ClientAnalyticsScript';
import dynamic from 'next/dynamic';
import ErrorsProvider from 'apps/web/contexts/Errors';
import { isDevelopment } from 'apps/web/src/constants';
import { logger } from 'apps/web/src/utils/logger';

const DynamicCookieBannerWrapper = dynamic(
Expand All @@ -39,51 +23,8 @@ const DynamicCookieBannerWrapper = dynamic(
},
);

coinbaseWallet.preference = 'all';

const connectors = connectorsForWallets(
[
{
groupName: 'Recommended',
wallets: [
coinbaseWallet,
metaMaskWallet,
uniswapWallet,
rainbowWallet,
phantomWallet,
walletConnectWallet,
],
},
],
{
projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID ?? 'dummy-id',
walletConnectParameters: {},
appName: 'Base.org',
appDescription: '',
appUrl: 'https://www.base.org/',
appIcon: '',
},
);

const config = createConfig({
connectors,
chains: [base, baseSepolia, mainnet],
transports: {
[base.id]: http(),
[baseSepolia.id]: http(),
[mainnet.id]: http(),
},
ssr: true,
});
const queryClient = new QueryClient();
const sprigEnvironmentId = process.env.NEXT_PUBLIC_SPRIG_ENVIRONMENT_ID;

const onchainKitConfig: AppConfig = {
appearance: {
mode: 'light',
},
};

type AppProvidersProps = {
children: React.ReactNode;
};
Expand Down Expand Up @@ -142,26 +83,14 @@ export default function AppProviders({ children }: AppProvidersProps) {
config={cookieManagerConfig}
>
<ClientAnalyticsScript />
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<OnchainKitProvider
chain={isDevelopment ? baseSepolia : base}
apiKey={process.env.NEXT_PUBLIC_ONCHAINKIT_API_KEY}
config={onchainKitConfig}
>
<RainbowKitProvider modalSize="compact">
<TooltipProvider>
<ExperimentsProvider>
<>
{children}
<DynamicCookieBannerWrapper />
</>
</ExperimentsProvider>
</TooltipProvider>
</RainbowKitProvider>
</OnchainKitProvider>
</QueryClientProvider>
</WagmiProvider>
<TooltipProvider>
<ExperimentsProvider>
<>
{children}
<DynamicCookieBannerWrapper />
</>
</ExperimentsProvider>
</TooltipProvider>
</CookieManagerProvider>
</ErrorsProvider>
);
Expand Down
22 changes: 22 additions & 0 deletions apps/web/app/CryptoProviders.dynamic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
'use client';

import { useEffect, useState } from 'react';
import { useErrors } from 'apps/web/contexts/Errors';

export function DynamicCryptoProviders({ children }: { children: React.ReactNode }) {
const [CryptoProvidersDynamic, setCryptoProvidersDynamic] =
useState<React.ComponentType<{ children: React.ReactNode }>>();
const { logError } = useErrors();

useEffect(() => {
import('apps/web/app/CryptoProviders')
.then((mod) => {
setCryptoProvidersDynamic(() => mod.default);
})
.catch((error) => logError(error, 'Failed to load CryptoProviders'));
}, [logError]);

if (!CryptoProvidersDynamic) return null;

return <CryptoProvidersDynamic>{children}</CryptoProvidersDynamic>;
}
78 changes: 78 additions & 0 deletions apps/web/app/CryptoProviders.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
'use client';

import { AppConfig, OnchainKitProvider } from '@coinbase/onchainkit';
import { connectorsForWallets, RainbowKitProvider } from '@rainbow-me/rainbowkit';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { isDevelopment } from 'apps/web/src/constants';
import { createConfig, http, WagmiProvider } from 'wagmi';
import { base, baseSepolia, mainnet } from 'wagmi/chains';
import {
coinbaseWallet,
metaMaskWallet,
phantomWallet,
rainbowWallet,
uniswapWallet,
walletConnectWallet,
} from '@rainbow-me/rainbowkit/wallets';

const connectors = connectorsForWallets(
[
{
groupName: 'Recommended',
wallets: [
coinbaseWallet,
metaMaskWallet,
uniswapWallet,
rainbowWallet,
phantomWallet,
walletConnectWallet,
],
},
],
{
projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID ?? 'dummy-id',
walletConnectParameters: {},
appName: 'Base.org',
appDescription: '',
appUrl: 'https://www.base.org/',
appIcon: '',
},
);

const config = createConfig({
connectors,
chains: [base, baseSepolia, mainnet],
transports: {
[base.id]: http(),
[baseSepolia.id]: http(),
[mainnet.id]: http(),
},
ssr: true,
});
const queryClient = new QueryClient();

type CryptoProvidersProps = {
children: React.ReactNode;
};

const onchainKitConfig: AppConfig = {
appearance: {
mode: 'light',
},
};

export default function CryptoProviders({ children }: CryptoProvidersProps) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<OnchainKitProvider
chain={isDevelopment ? baseSepolia : base}
apiKey={process.env.NEXT_PUBLIC_ONCHAINKIT_API_KEY}
config={onchainKitConfig}
>
<RainbowKitProvider modalSize="compact">{children}</RainbowKitProvider>
</OnchainKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
}
3 changes: 3 additions & 0 deletions apps/web/app/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
@tailwind components;
@tailwind utilities;

@import '@rainbow-me/rainbowkit/styles.css';
@import '@coinbase/onchainkit/styles.css';

/* For Webkit-based browsers (Chrome, Safari and Opera) */
:not(.scrollbar)::-webkit-scrollbar {
display: none;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { useCopyToClipboard, useMediaQuery } from 'usehooks-ts';
import { useAccount, useSwitchChain } from 'wagmi';
import ChainDropdown from 'apps/web/src/components/ChainDropdown';
import { useSearchParams } from 'next/navigation';
import { DynamicCryptoProviders } from 'apps/web/app/CryptoProviders.dynamic';

export enum ConnectWalletButtonVariants {
BaseOrg,
Expand All @@ -37,6 +38,16 @@ type ConnectWalletButtonProps = {
connectWalletButtonVariant: ConnectWalletButtonVariants;
};

export function DynamicWrappedConnectWalletButton({
connectWalletButtonVariant = ConnectWalletButtonVariants.BaseOrg,
}: ConnectWalletButtonProps) {
return (
<DynamicCryptoProviders>
<ConnectWalletButton connectWalletButtonVariant={connectWalletButtonVariant} />
</DynamicCryptoProviders>
)
}

export function ConnectWalletButton({
connectWalletButtonVariant = ConnectWalletButtonVariants.BaseOrg,
}: ConnectWalletButtonProps) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,23 @@ import Card from 'apps/web/src/components/base-org/Card';
import { Icon } from 'apps/web/src/components/Icon/Icon';
import { base, mainnet } from 'viem/chains';
import { useGasPrice } from 'wagmi';
import { DynamicCryptoProviders } from 'apps/web/app/CryptoProviders.dynamic';

const convertWeiToMwei = (weiValue: bigint): number => {
// 1 mwei = 10^6 wei
const mweiValue = Number(weiValue) / 1_000_000;
return Number(mweiValue.toFixed(2)); // Round to 2 decimal places
};

export default function GasPriceDropdown() {
export function DynamicWrappedGasPriceDropdown() {
return (
<DynamicCryptoProviders>
<GasPriceDropdown />
</DynamicCryptoProviders>
);
}

export function GasPriceDropdown() {
const { data: baseGasPriceInWei } = useGasPrice({
chainId: base.id,
query: {
Expand All @@ -26,7 +35,7 @@ export default function GasPriceDropdown() {

return (
<div className="group relative hidden md:block">
<div className="flex flex cursor-pointer items-center gap-2 rounded-xl bg-black px-4 py-3 transition-all group-hover:bg-[#333]">
<div className="flex flex-row cursor-pointer items-center gap-2 rounded-xl bg-black px-4 py-3 transition-all group-hover:bg-[#333]">
<span className="animate-pulse text-palette-positive">
<Icon name="blueCircle" color="currentColor" height="0.75rem" width="0.75rem" />
</span>
Expand Down
35 changes: 21 additions & 14 deletions apps/web/src/components/base-org/shared/TopNavigation/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
'use client';

import AnalyticsProvider from 'apps/web/contexts/Analytics';
import Link from 'next/link';
import logo from './assets/logo.svg';
import { Suspense } from 'react';
import Image, { StaticImageData } from 'next/image';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import AnalyticsProvider from 'apps/web/contexts/Analytics';
import logo from 'apps/web/src/components/base-org/shared/TopNavigation/assets/logo.svg';
import MenuDesktop from 'apps/web/src/components/base-org/shared/TopNavigation/MenuDesktop';
import MenuMobile from 'apps/web/src/components/base-org/shared/TopNavigation/MenuMobile';
import { DynamicWrappedGasPriceDropdown } from 'apps/web/src/components/base-org/shared/TopNavigation/GasPriceDropdown';
import {
ConnectWalletButton,
ConnectWalletButtonVariants,
DynamicWrappedConnectWalletButton,
} from 'apps/web/src/components/ConnectWalletButton/ConnectWalletButton';
import MenuDesktop from 'apps/web/src/components/base-org/shared/TopNavigation/MenuDesktop';
import MenuMobile from 'apps/web/src/components/base-org/shared/TopNavigation/MenuMobile';
import GasPriceDropdown from 'apps/web/src/components/base-org/shared/TopNavigation/GasPriceDropdown';
import { Suspense } from 'react';

export type SubItem = {
name: string;
Expand Down Expand Up @@ -91,7 +92,11 @@ const links: TopNavigationLink[] = [
},
];

const cryptoExcludedPaths = ['/jobs', '/about', '/ecosystem', '/getstarted'];

export default function TopNavigation() {
const pathname = usePathname();
const showGasDropdownAndConnectWallet = !cryptoExcludedPaths.includes(pathname ?? '');
return (
<AnalyticsProvider context="navbar">
<nav className="fixed top-0 z-50 w-full shrink-0 px-[1rem] py-4 md:px-[1.5rem] lg:px-[2rem]">
Expand All @@ -101,7 +106,7 @@ export default function TopNavigation() {
<Link href="/" className="flex min-h-[3rem] min-w-[3rem]">
<Image src={logo as StaticImageData} alt="Base Logo" />
</Link>
<GasPriceDropdown />
{showGasDropdownAndConnectWallet && <DynamicWrappedGasPriceDropdown />}
</div>

<div className="hidden md:inline-block">
Expand All @@ -114,11 +119,13 @@ export default function TopNavigation() {

{/* Connect Wallet button */}
<div className="flex items-end justify-end md:min-w-[16rem]">
<Suspense>
<ConnectWalletButton
connectWalletButtonVariant={ConnectWalletButtonVariants.BaseOrg}
/>
</Suspense>
{showGasDropdownAndConnectWallet && (
<Suspense>
<DynamicWrappedConnectWalletButton
connectWalletButtonVariant={ConnectWalletButtonVariants.BaseOrg}
/>
</Suspense>
)}
</div>
</div>
</nav>
Expand Down

0 comments on commit 0c7febf

Please sign in to comment.