ทำปุ่ม Connect Wallet เชื่อมต่อ Blockchain ง่ายๆ ด้วย Rainbowkit

Published on
Web3
web3-connect-wallet-with-rainbowkit
Discord

วิธีการทำปุ่ม 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 ให้

ตัวอย่างหน้าเว็บที่มี 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 ก่อน

_app.tsx
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 ก็จะได้แบบนี้

_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 เพื่อทดสอบ

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
Show Balance after Connect

จะเห็นว่า ตัว 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 ตัวเอง ก็ทำได้ เป็นจุดเริ่มต้น ลองไปเล่นกันดูครับ

หวังว่าบทความนี้จะเป็นไอเดีย ให้ใครหลายๆคนนะครับ ขอบคุณครับ

อ่านเพิ่มเติม

Buy Me A Coffee
Authors
Discord