วิธีการทำปุ่ม Connect Wallet สำหรับ Decentralize App (dApp) ปัจจุบันนั้นง่ายมาก และมีหลาย Library ให้เลือกใช้ เช่น
แต่วันนี้จะเป็นตัวอย่างการใช้ RainbowKit และ wagmi (Hooks) ในการทำปุ่ม Connect Wallet นะครับ
Stacks
- RainbowKit (0.7.1) - Library ที่ช่วยในการ Connect Wallet
- Wagmi - React Hooks สำหรับ Ethereum
- Ethers.js - Web3 Client สำหรับ interact กับ Smart Contract
ข้อดีคือ
- รองรับการ Switch Network ให้เราเลยกรณีที่ Metamask เราไม่มี Network มันก็จะขอ request เพื่อ add new network ให้เอง
- UI พร้อมใช้งาน มีการ handle การ Refresh และ auto connect
- ตัว Connect Button กรณีที่ connected แล้ว ก็สามารถแสดง balance และ address ได้เลย
Start Project
เราสามารถสร้างโปรเจ็คง่ายๆ ได้ด้วยคำสั่งด้านล่างนี้ จะได้เป็น Scaffold Project ที่ประกอบไปด้วย Rainbow Kit + wagmi และ Next.js
npm init @rainbow-me/rainbowkit@latestจะมีหน้าต่างขึ้นมาถามว่าเราจะให้ชื่อโปรเจ็ค (folder) ว่าอะไร ก็ใส่ที่ต้องการไป รอติดตั้ง dependencies ซักพัก เราก็จะได้เว็บ Next.js Starter ที่มีตัวอย่างการ Connect Wallet ให้

ลองสำรวจภายในโปรเจ็คดูซักหน่อยว่าตัว initial เค้ามีอะไรมาให้บ้าง
├── README.md├── next-env.d.ts├── next.config.js├── package-lock.json├── package.json├── pages│ ├── _app.tsx│ └── index.tsx├── styles│ ├── Home.module.css│ └── globals.css└── tsconfig.jsonตัวโปรเจ็ค เป็น Next.js และก็มีการ config Provider ที่ไฟล์ _app.tsx
<RainbowKitProvider chains={chains}> <Component {...pageProps} /></RainbowKitProvider>จะเห็นว่า เพียงแค่เรากำหนด <RainbowKitProvider> เราก็สามารถใช้งานปุ่ม Connect Button ได้แล้ว
ตัวปุ่มในไฟล์ index.tsx จะเป็น built-in component ที่มากับ Rainbowkit
<ConnectButton />Create Project เอง
ทีนี้เรามาลอง Config ตามตัว boilerplate ตั้งแต่ต้น เพื่อจะได้เข้าใจกันมากขึ้น ว่ามันต้อง config อะไรบ้าง โดยการเริ่มโปรเจ็คใหม่ ด้วย create-next-app กันครับ
สร้างโปรเจ็ค แบบ TypeScript
npx create-next-app@latest --ts✔ What is your project named? … rainbowkit-app-nextjsผมตั้งชื่อให้มันว่า rainbowkit-app-nextjs เมื่อได้โปรเจ็ค Next.js เรียบร้อยแล้ว ก็ เปิด folder ขึ้นมา แล้วติดตั้ง dependencies รวมถึงติดตั้ง ethers.js wagmi และ rainbowkit ครับ
npm install @rainbow-me/rainbowkit wagmi ethersเปิดไฟล์ _app.tsx ขึ้นมา จากนั้น import import css style ของ RainbowKit ก่อน
import '@rainbow-me/rainbowkit/styles.css'ต่อมาตรง MyApp เราจะ Wrap Provider ของ Wagmi และ Rainbowkit
import { WagmiConfig } from 'wagmi';import { RainbowKitProvider } from '@rainbow-me/rainbowkit';
function MyApp({ Component, pageProps }: AppProps) { return ( <WagmiConfig client={wagmiClient}> <RainbowKitProvider chains={chains}> <Component {...pageProps} /> </RainbowKitProvider> </WagmiConfig> )}สาเหตุที่ต้องใช้ WagmiConfig เนื่องจากว่า ตัว RainbowKit นั้นใช้ hooks ของ wagmi นั่นเอง ถ้าเราไม่มี wagmi ตัว rainbowkit ก็ใช้งานไม่ได้เช่นกัน
ต่อมา เราจะเห็นว่ายังมี error ของ wagmiClient และ chains ที่เรายังไม่ได้สร้าง
เราจะมา กำหนด wagmiClient โดยใช้ createClient ของ wagmi สิ่งที่เราต้องใช้คือ chains และ providers
import { chain, configureChains, createClient, WagmiConfig } from 'wagmi'import { RainbowKitProvider, getDefaultWallets } from '@rainbow-me/rainbowkit'import { publicProvider } from 'wagmi/providers/public'
const { chains, provider } = configureChains( [chain.mainnet, chain.polygon, chain.goerli], [publicProvider()])
const { connectors } = getDefaultWallets({ appName: 'My RainbowKit App', chains})
const wagmiClient = createClient({ autoConnect: true, connectors, provider})- หากเราสังเกตตัว
Providerเราสามารถใช้ Alchemy หรือ Infura แทน PublicProvider ก็ได้ครับ configureChains()เพื่อกำหนดว่า เราจะมี chains อะไรให้เลือกบ้างgetDefaultWallets()ของ RainbowKit จะมี list ของ default เช่น Rainbow, Metamask, WalletConnect เราสามารถ custom เองได้เหมือนกัน
สุดท้ายไฟล์ _app.tsx ก็จะได้แบบนี้
import '../styles/globals.css'import '@rainbow-me/rainbowkit/styles.css'
import type { AppProps } from 'next/app'
import { chain, configureChains, createClient, WagmiConfig } from 'wagmi'import { RainbowKitProvider, getDefaultWallets } from '@rainbow-me/rainbowkit'import { publicProvider } from 'wagmi/providers/public'
const { chains, provider } = configureChains( [chain.mainnet, chain.polygon, chain.goerli], [publicProvider()])
const { connectors } = getDefaultWallets({ appName: 'My RainbowKit App', chains,})
const wagmiClient = createClient({ autoConnect: true, connectors, provider,})
function MyApp({ Component, pageProps }: AppProps) { return ( <WagmiConfig client={wagmiClient}> <RainbowKitProvider chains={chains}> <Component {...pageProps} /> </RainbowKitProvider> </WagmiConfig> )}
export default MyAppเพิ่มปุ่ม Connect Wallet ที่หน้า index.tsx เพื่อทดสอบ
import { ConnectButton } from '@rainbow-me/rainbowkit'
const Home: NextPage = () => { return ( <div className={styles.container}> <Head>... </Head>
<main className={styles.main}> <h1 className={styles.title}> Welcome to <a href="https://nextjs.org">Next.js!</a> </h1>
<ConnectButton /> /* โค๊ดที่เหลือ */ )}ทดสอบ start server บน local เพื่อลองดูว่าได้ปุ่ม Connect Wallet มั้ย?
npm run dev
จะเห็นว่า ตัว Component ConnectButton มันก็จะโชว์ Chain และก็ Balance ของเรา รวมถึง handle disconnect / switch network ต่างๆ ให้เราเองโดยที่เราไม่ต้องมาจัดการ state เองเลย
Custom ConnectButton
เราสามารถ custom ได้ เช่น ไม่ต้องแสดง Balance, chain status จะโชว์แค่ icon หรือ title ก็เปลี่ยนได้ผ่าน props เช่น
<ConnectButton label="Log in" showBalance={false} chainStatus="icon" accountStatus="address" />นอกจากนี้ก็ยังสามารถ Custom ตัว Popup (Modal) ได้ ว่าจะให้มันมีขนาดเล็ก / ใหญ่ / ทำ CSS เองได้ หรือการกำหนด Wallet List เอง อยากใส่ Wallet ตัวเอง ก็ทำได้ เป็นจุดเริ่มต้น ลองไปเล่นกันดูครับ
หวังว่าบทความนี้จะเป็นไอเดีย ให้ใครหลายๆคนนะครับ ขอบคุณครับ
อ่านเพิ่มเติม
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust