Skip to content

Commit

Permalink
add web3modal
Browse files Browse the repository at this point in the history
  • Loading branch information
glitch-txs committed Oct 25, 2023
1 parent 5095d92 commit ccad142
Show file tree
Hide file tree
Showing 16 changed files with 94 additions and 25,604 deletions.
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# Public Variables
# -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
# WalletConnect Project ID - Generate one in https://cloud.walletconnect.com/
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=

# Public Provider(s) - Useful for testing
NEXT_PUBLIC_USE_PUBLIC_PROVIDER=true

Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
![TS](https://badgen.net/badge/-/TypeScript?icon=typescript&label&labelColor=blue&color=555555)
[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](http://perso.crans.org/besson/LICENSE.html)

Web3 App Template built using Next.js, RainbowKit, Tailwind, Sign-In With Ethereum, and more.
Web3 App Template built using Next.js, Web3Modal, Tailwind, Sign-In With Ethereum, and more.

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fturbo-eth%2Ftemplate-web3-app&project-name=TurboETH&repository-name=turbo-eth&demo-title=TurboETH&env=NEXTAUTH_SECRET,DATABASE_URL&envDescription=How%20to%20get%20these%20env%20variables%3A&envLink=https%3A%2F%2Fgithub.com%2Fturbo-eth%2Ftemplate-web3-app%2Fblob%integrations%2F.env.example)

Expand All @@ -19,7 +19,7 @@ Web3 App Template built using Next.js, RainbowKit, Tailwind, Sign-In With Ethere
- [UI Components](https://docs.turboeth.xyz/getting-started/design-system)
- [Backend Database](https://docs.turboeth.xyz/getting-started/database)
- Core Integrations
- [🌈 RainbowKit](https://docs.turboeth.xyz/integration/rainbowkit)
- [Web3Modal](https://docs.walletconnect.com/web3modal/about)
- [🔏 Sign-In With Ethereum](https://docs.turboeth.xyz/integration/sign-in-with-ethereum)
- Smart Contract Integrations
- [ERC20](https://docs.turboeth.xyz/integration/smart-contract-erc20)
Expand Down Expand Up @@ -50,7 +50,7 @@ pnpm build
### Web3 Core

- [WAGMI CLI](https://wagmi.sh/cli/getting-started) - Automatic React Hook Generation
- [RainbowKit](https://www.rainbowkit.com/) - Wallet connection manager
- [Web3Modal](https://docs.walletconnect.com/web3modal/about) - Wallet connection manager
- [Sign-In With Ethereum](https://login.xyz/) - Account authentication

### Web2 Frameworks
Expand Down
104 changes: 32 additions & 72 deletions components/blockchain/wallet-connect-custom.tsx
Original file line number Diff line number Diff line change
@@ -1,89 +1,49 @@
import { HTMLAttributes } from "react"
import { ConnectButton } from "@rainbow-me/rainbowkit"

import { Button } from "../ui/button"
import { useWeb3Modal } from "@web3modal/wagmi/react"
import { useAccount } from "wagmi"

interface WalletConnectCustomProps extends HTMLAttributes<HTMLDivElement> {
classNameConnect?: string
classNameConnected?: string
classNameWrongNetwork?: string
classNameNetwork?: string
labelConnect?: string
labelWrongNetwork?: string
labelNetwork?: string
}

export const WalletConnectCustom = ({
className,
classNameConnect,
classNameConnected,
classNameNetwork,
labelConnect = "Connect Wallet",
labelWrongNetwork = "Wrong Network",
labelNetwork = "Open Network Modal",
...props
}: WalletConnectCustomProps) => {
return (
<ConnectButton.Custom>
{({
account,
chain,
openChainModal,
openConnectModal,
authenticationStatus,
}) => {
const connected =
account &&
chain &&
(!authenticationStatus || authenticationStatus === "authenticated")
// 4. Use modal hook
const { open } = useWeb3Modal()
const { address, isConnected } = useAccount()

return (
<div className={className} {...props}>
{(() => {
if (!connected) {
return (
<>
<Button variant="default" onClick={openConnectModal}>
{labelConnect}
</Button>
</>
)
}

if (chain.unsupported) {
return (
<Button variant="destructive" onClick={openChainModal}>
{labelWrongNetwork}
</Button>
)
}
return (
<div {...props}>
{isConnected && address ? (
<button className={classNameConnected} onClick={() => open()}>
{`${address.slice(0, 8)}...${address.slice(34, 42)}`}
</button>
) : (
<button
className={classNameConnect}
onClick={() => open({ view: "Account" })}
>
{labelConnect}
</button>
)}

return (
<div>
<Button variant="default" onClick={openChainModal}>
{chain.hasIcon && (
<div
style={{
background: chain.iconBackground,
width: 18,
height: 18,
borderRadius: 999,
overflow: "hidden",
marginRight: 4,
}}
>
{chain.iconUrl && (
<img
alt={chain.name ?? "Chain icon"}
src={chain.iconUrl}
style={{ width: 18, height: 18 }}
/>
)}
</div>
)}
<span className="ml-1 text-lg lowercase">{chain.name}</span>
</Button>
</div>
)
})()}
</div>
)
}}
</ConnectButton.Custom>
<button
className={classNameNetwork}
onClick={() => open({ view: "Networks" })}
>
{labelNetwork}
</button>
</div>
)
}

Expand Down
13 changes: 1 addition & 12 deletions components/blockchain/wallet-connect.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,12 @@
import { HtmlHTMLAttributes } from "react"
import { ConnectButton } from "@rainbow-me/rainbowkit"

export const WalletConnect = ({
className,
...props
}: HtmlHTMLAttributes<HTMLSpanElement>) => {
return (
<span className={className} {...props}>
<ConnectButton
showBalance={false}
accountStatus={{
smallScreen: "avatar",
largeScreen: "avatar",
}}
chainStatus={{
smallScreen: "icon",
largeScreen: "icon",
}}
/>
<w3m-button />
</span>
)
}
74 changes: 33 additions & 41 deletions components/providers/rainbow-kit.tsx
Original file line number Diff line number Diff line change
@@ -1,57 +1,49 @@
"use client"

import "@rainbow-me/rainbowkit/styles.css"

import { ReactNode } from "react"
import {
connectorsForWallets,
darkTheme,
lightTheme,
RainbowKitProvider,
} from "@rainbow-me/rainbowkit"
import {
coinbaseWallet,
injectedWallet,
metaMaskWallet,
rainbowWallet,
walletConnectWallet,
} from "@rainbow-me/rainbowkit/wallets"
import { ReactNode, useEffect } from "react"
import { EIP6963Connector } from "@web3modal/wagmi"
import { createWeb3Modal, useWeb3ModalTheme } from "@web3modal/wagmi/react"
import { createConfig, WagmiConfig } from "wagmi"
import { CoinbaseWalletConnector } from "wagmi/connectors/coinbaseWallet"
import { InjectedConnector } from "wagmi/connectors/injected"
import { WalletConnectConnector } from "wagmi/connectors/walletConnect"

import { chains, publicClient, webSocketPublicClient } from "@/config/networks"
import { siteConfig } from "@/config/site"
import { metadata } from "@/config/site"
import { useColorMode } from "@/lib/state/color-mode"

const connectors = connectorsForWallets([
{
groupName: "Recommended",
wallets: [
injectedWallet({ chains }),
metaMaskWallet({ chains }),
rainbowWallet({ chains }),
coinbaseWallet({ chains, appName: siteConfig.name }),
walletConnectWallet({ chains }),
],
},
])
const projectId = process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!
if (!projectId) {
throw new Error("Project ID is undefined")
}

const wagmiConfig = createConfig({
autoConnect: true,
connectors,
connectors: [
new WalletConnectConnector({
chains,
options: { projectId, showQrModal: false, metadata },
}),
new EIP6963Connector({ chains }),
new InjectedConnector({ chains, options: { shimDisconnect: true } }),
new CoinbaseWalletConnector({
chains,
options: { appName: metadata.name },
}),
],
publicClient,
webSocketPublicClient,
})

export function RainbowKit({ children }: { children: ReactNode }) {
createWeb3Modal({ wagmiConfig, projectId, chains })

export function Web3Modal({ children }: { children: ReactNode }) {
const [colorMode] = useColorMode()
return (
<WagmiConfig config={wagmiConfig}>
<RainbowKitProvider
chains={chains}
theme={colorMode == "dark" ? darkTheme() : lightTheme()}
>
{children}
</RainbowKitProvider>
</WagmiConfig>
)
const { setThemeMode } = useWeb3ModalTheme()

useEffect(() => {
if (colorMode !== "system") setThemeMode(colorMode)
}, [colorMode])

return <WagmiConfig config={wagmiConfig}>{children}</WagmiConfig>
}
6 changes: 3 additions & 3 deletions components/providers/root-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Provider as RWBProvider } from "react-wrap-balancer"

import { useIsMounted } from "@/lib/hooks/use-is-mounted"
import HandleWalletEvents from "@/components/blockchain/handle-wallet-events"
import { RainbowKit } from "@/components/providers/rainbow-kit"
import { Web3Modal } from "@/components/providers/web3modal"

const queryClient = new QueryClient()
interface RootProviderProps {
Expand All @@ -25,9 +25,9 @@ export default function RootProvider({ children }: RootProviderProps) {
>
<QueryClientProvider client={queryClient}>
<RWBProvider>
<RainbowKit>
<Web3Modal>
<HandleWalletEvents>{children}</HandleWalletEvents>
</RainbowKit>
</Web3Modal>
</RWBProvider>
</QueryClientProvider>
</ThemeProvider>
Expand Down
9 changes: 4 additions & 5 deletions components/shared/example-demos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,15 +99,14 @@ const demos = [
),
},
{
title: "Rainbowkit",
description:
"The best way to connect a wallet. Designed for everyone. Built for developers.",
title: "Web3Modal",
description: "All in one SDK for connecting your app to your wallet.",
demo: (
<div className="flex items-center justify-center space-x-20">
<Image
alt="Rainbow logo"
alt="Web3Modal logo"
height={100}
src="/integrations/rainbowkit.svg"
src="/integrations/walletconnect.svg"
width={100}
/>
</div>
Expand Down
8 changes: 7 additions & 1 deletion config/networks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,14 @@ export const ETH_CHAINS_DEV =

export const CHAINS: Chain[] =
process.env.NODE_ENV === "production" ? ETH_CHAINS_PROD : ETH_CHAINS_DEV

const projectId = process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID!
if (!projectId) {
throw new Error("Project ID is undefined")
}

const PROVIDERS: ChainProviderFn<Chain>[] = [walletConnectProvider({ projectId })]

const PROVIDERS: ChainProviderFn<Chain>[] = []

if (env.NEXT_PUBLIC_ALCHEMY_API_KEY) {
if (!env.NEXT_PUBLIC_ALCHEMY_API_KEY)
Expand Down
1 change: 1 addition & 0 deletions env.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const env = createEnv({
NEXT_PUBLIC_SITE_URL: z.string().url().optional(),
},
runtimeEnv: {
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID,
NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
DATABASE_URL: process.env.DATABASE_URL,
APP_ADMINS: process.env.APP_ADMINS,
Expand Down
3 changes: 1 addition & 2 deletions integrations/erc20/components/erc20-read.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"use client"

import { HTMLAttributes } from "react"
import { ConnectButton } from "@rainbow-me/rainbowkit"
import { formatUnits } from "viem"
import { Address, useAccount } from "wagmi"

Expand Down Expand Up @@ -217,7 +216,7 @@ export function ERC20Read({
</IsWalletConnected>
<IsWalletDisconnected>
<div className="flex items-center justify-center gap-10">
<ConnectButton />
<w3m-button />
</div>
</IsWalletDisconnected>
</>
Expand Down
3 changes: 1 addition & 2 deletions integrations/erc20/components/erc20-write-mint.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { ConnectButton } from "@rainbow-me/rainbowkit"
import { useForm } from "react-hook-form"
import { useDebounce } from "usehooks-ts"
import { BaseError, parseEther } from "viem"
Expand Down Expand Up @@ -99,7 +98,7 @@ export function ERC20WriteMint({ address }: ERC20WriteMintProps) {
</IsWalletConnected>
<IsWalletDisconnected>
<div className="flex items-center justify-center gap-10">
<ConnectButton />
<w3m-button />
</div>
</IsWalletDisconnected>
</>
Expand Down
1 change: 1 addition & 0 deletions next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const nextConfig = {
loader: "next-image-loader",
options: { assetPrefix: "" },
})
config.externals.push("pino-pretty", "lokijs", "encoding")
return config
},
...withPWA({
Expand Down
Loading

0 comments on commit ccad142

Please sign in to comment.