Skip to main content

Documentation Index

Fetch the complete documentation index at: https://daehan-base.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Wagmi를 사용하여 Base Account 프로바이더에 접근하고 올바른 SIWE(Sign-In With Ethereum) 인증 플로우를 따름으로써 Base로 로그인을 구현하는 방법을 알아보세요.

사전 요구 사항

이 가이드를 따르기 전에 Wagmi와 Base Account를 설정했는지 확인하세요.

개요

Wagmi에서 Base로 로그인을 구현하려면 다음이 필요합니다:
  1. Wagmi에서 Base Account 커넥터 가져오기
  2. 커넥터에서 내부 프로바이더 접근
  3. signInWithEthereum 기능으로 wallet_connect 사용
  4. 백엔드에서 서명 검증
이는 사용자 인증 가이드에 표시된 것과 동일한 플로우를 따르되 Wagmi의 커넥터 시스템과 통합됩니다.
Wagmi 내에서 최신 버전의 Base Account SDK에 접근하려면 다음 명령어를 사용하여 오버라이드할 수 있습니다:
npm pkg set overrides.@base-org/account="latest"
또는 특정 버전을 사용하려면:
npm pkg set overrides.@base-org/account="2.2.0"
오버라이드가 적용되도록 node_modulespackage-lock.json을 삭제하고 새로 설치해야 합니다.

구현

코드 스니펫

import { useState } from 'react'
import { useConnect, useAccount, useDisconnect } from 'wagmi'
import { baseAccount } from 'wagmi/connectors'

export function SignInWithBase() {
  const [isLoading, setIsLoading] = useState(false)
  const [error, setError] = useState<string | null>(null)
  const { isConnected, address } = useAccount()
  const { connectAsync, connectors } = useConnect()
  const { disconnect } = useDisconnect()

  // Base Account 커넥터 찾기
  const baseAccountConnector = connectors.find(
    connector => connector.id === 'baseAccount'
  )

  const handleSignIn = async () => {
    if (!baseAccountConnector) {
      setError('Base Account 커넥터를 찾을 수 없습니다')
      return
    }

    setIsLoading(true)
    setError(null)

    try {
      // 1 — 새로운 nonce 가져오기 (로컬에서 생성하거나 백엔드에서 미리 가져오기)
      const nonce = window.crypto.randomUUID().replace(/-/g, '')
      // 또는 서버에서 미리 가져오기
      // const nonce = await fetch('/auth/nonce').then(r => r.text())

      // 2 — 연결하고 프로바이더 가져오기
      await connectAsync({ connector: baseAccountConnector })
      const provider = baseAccountConnector.provider

      // 3 — wallet_connect로 인증
      const authResult = await provider.request({
        method: 'wallet_connect',
        params: [{
          version: '1',
          capabilities: {
            signInWithEthereum: { 
              nonce, 
              chainId: '0x2105' // Base 메인넷 - 8453
            }
          }
        }]
      })

      const { accounts } = authResult
      const { address, capabilities } = accounts[0]
      const { message, signature } = capabilities.signInWithEthereum

      // 4 — 백엔드에서 검증
      await fetch('/auth/verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ address, message, signature })
      })
    } catch (err: any) {
      console.error(`err ${err}`)
      setError(err.message || '로그인 실패')
    } finally {
      setIsLoading(false)
    }
  }

  if (isConnected) {
    return (
      <div className="flex items-center gap-4">
        <span className="font-mono text-sm">{address}</span>
        <button onClick={() => disconnect()}>로그아웃</button>
      </div>
    )
  }

  return (
    <button onClick={handleSignIn} disabled={isLoading}>
      {isLoading ? '로그인 중...' : 'Base로 로그인'}
    </button>
  )
}

3. 미리 구축된 버튼 컴포넌트 사용

공식 SignInWithBaseButton 버튼 컴포넌트를 사용할 수도 있습니다:
// components/SignInButton.tsx
import { SignInWithBaseButton } from '@base-org/account-ui/react'
import { useConnect } from 'wagmi'

export function SignInButton() {
  const { connectAsync, connectors } = useConnect()

  const handleSignIn = async () => {
    const baseAccountConnector = connectors.find(
      connector => connector.id === 'baseAccount'
    )

    if (!baseAccountConnector) return

    try {
      // Nonce 생성
      const nonce = window.crypto.randomUUID().replace(/-/g, '')

      // 연결하고 프로바이더 가져오기
      await connectAsync({ connector: baseAccountConnector })
      const provider = baseAccountConnector.provider

      // SIWE 인증 수행
      const authResult = await provider.request({
        method: 'wallet_connect',
        params: [{
          version: '1',
          capabilities: {
            signInWithEthereum: { 
              nonce, 
              chainId: '0x2105'
            }
          }
        }]
      })

      // 서명 추출 및 검증
      const { accounts } = authResult
      const { address, capabilities } = accounts[0]
      const { message, signature } = capabilities.signInWithEthereum

      // 백엔드로 전송하여 검증
      await fetch('/auth/verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ address, message, signature })
      })
    } catch (error) {
      console.error('Authentication failed:', error)
    }
  }

  return (
    <SignInWithBaseButton
      colorScheme="light"
      onClick={handleSignIn}
    />
  )
}
브랜드 가이드라인을 준수해 주세요SignInWithBaseButton을 사용할 경우 애플리케이션 전체의 일관성을 위해 Base 브랜드 가이드라인을 준수해 주세요.