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 프로바이더 메서드를 사용하여 서브 어카운트를 생성하고 관리하는 방법을 알아보세요.

사전 요구 사항

다음이 완료되어 있는지 확인하세요:

개요

서브 어카운트를 통해 스펜드 퍼미션을 사용하여 상위 계정의 잔액을 사용할 수 있는 자식 계정을 생성할 수 있습니다. 이를 통해 빈번한 사용자 서명의 필요성을 줄이고 사용자 경험을 향상시킵니다.

서브 어카운트 생성

Base Account 프로바이더를 사용하여 서브 어카운트를 생성합니다:
import { useAccount, useConnector } from 'wagmi'
import { useState } from 'react'

export function CreateSubAccount() {
  const { address, isConnected } = useAccount()
  const connector = useConnector()
  const [subAccount, setSubAccount] = useState<string | null>(null)
  const [isCreating, setIsCreating] = useState(false)

  const createSubAccount = async () => {
    if (!connector || !isConnected) return

    setIsCreating(true)
    try {
      const provider = connector.provider
      
      // 새 서브 어카운트 생성
      const result = await provider?.request({
        method: 'wallet_addSubAccount',
        params: [{
          version: '1.0',
          chainId: `0x${Number(8453).toString(16)}`, // Base 메인넷
          from: address,
        }]
      })

      if (result?.subAccount) {
        setSubAccount(result.subAccount)
        console.log('Sub Account created:', result.subAccount)
      }
    } catch (error) {
      console.error('Failed to create Sub Account:', error)
    } finally {
      setIsCreating(false)
    }
  }

  return (
    <div className="space-y-4">
      <h3 className="text-lg font-semibold">서브 어카운트 관리</h3>
      
      {!subAccount ? (
        <button
          onClick={createSubAccount}
          disabled={!isConnected || isCreating}
          className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
        >
          {isCreating ? '서브 어카운트 생성 중...' : '서브 어카운트 생성'}
        </button>
      ) : (
        <div className="p-4 bg-green-50 border border-green-200 rounded">
          <p className="text-sm text-green-700">
            서브 어카운트 생성됨: <span className="font-mono">{subAccount}</span>
          </p>
        </div>
      )}
    </div>
  )
}

서브 어카운트 목록 조회

연결된 지갑의 기존 서브 어카운트를 조회합니다:
import { useAccount, useConnector } from 'wagmi'
import { useState, useEffect } from 'react'

export function SubAccountsList() {
  const { address, isConnected } = useAccount()
  const connector = useConnector()
  const [subAccounts, setSubAccounts] = useState<string[]>([])
  const [isLoading, setIsLoading] = useState(false)

  const fetchSubAccounts = async () => {
    if (!connector || !isConnected) return

    setIsLoading(true)
    try {
      const provider = connector.provider
      
      const result = await provider?.request({
        method: 'wallet_getSubAccounts',
        params: [{
          version: '1.0',
          chainId: `0x${Number(8453).toString(16)}`,
          from: address,
        }]
      })

      if (result?.subAccounts) {
        setSubAccounts(result.subAccounts)
      }
    } catch (error) {
      console.error('Failed to fetch Sub Accounts:', error)
    } finally {
      setIsLoading(false)
    }
  }

  useEffect(() => {
    if (isConnected) {
      fetchSubAccounts()
    }
  }, [isConnected, address])

  return (
    <div className="space-y-4">
      <div className="flex items-center justify-between">
        <h3 className="text-lg font-semibold">내 서브 어카운트</h3>
        <button
          onClick={fetchSubAccounts}
          disabled={isLoading}
          className="px-3 py-1 bg-gray-500 text-white rounded text-sm"
        >
          {isLoading ? '로딩 중...' : '새로고침'}
        </button>
      </div>

      {subAccounts.length === 0 ? (
        <p className="text-gray-500">서브 어카운트가 없습니다</p>
      ) : (
        <div className="space-y-2">
          {subAccounts.map((subAccount, index) => (
            <div
              key={subAccount}
              className="p-3 bg-blue-50 border border-blue-200 rounded"
            >
              <div className="flex items-center justify-between">
                <span className="font-mono text-sm">{subAccount}</span>
                <span className="text-xs text-blue-600">서브 어카운트 #{index + 1}</span>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  )
}

트랜잭션에 서브 어카운트 사용

서브 어카운트가 있으면 트랜잭션 수행에 사용할 수 있습니다:
import { useAccount, useConnector, useWriteContract } from 'wagmi'
import { useState } from 'react'

export function SubAccountTransactions() {
  const { address } = useAccount()
  const connector = useConnector()
  const [selectedSubAccount, setSelectedSubAccount] = useState('')
  const [isLoading, setIsLoading] = useState(false)

  const sendTransactionFromSubAccount = async () => {
    if (!connector || !selectedSubAccount) return

    setIsLoading(true)
    try {
      const provider = connector.provider
      
      // 서브 어카운트를 사용하여 트랜잭션 전송
      const result = await provider?.request({
        method: 'wallet_sendCalls',
        params: [{
          version: '1.0',
          chainId: `0x${Number(8453).toString(16)}`,
          from: selectedSubAccount, // 서브 어카운트를 발신자로 사용
          calls: [{
            to: '0x...' as `0x${string}`,
            value: '0x0',
            data: '0x' as `0x${string}`
          }]
        }]
      })

      console.log('Transaction sent from Sub Account:', result)
    } catch (error) {
      console.error('Sub Account transaction failed:', error)
    } finally {
      setIsLoading(false)
    }
  }

  return (
    <div className="space-y-4">
      <h3 className="text-lg font-semibold">서브 어카운트 트랜잭션</h3>
      
      <div>
        <label className="block mb-2">서브 어카운트 선택:</label>
        <input
          type="text"
          value={selectedSubAccount}
          onChange={(e) => setSelectedSubAccount(e.target.value)}
          className="w-full p-2 border rounded"
          placeholder="0x... (서브 어카운트 주소)"
        />
      </div>

      <button
        onClick={sendTransactionFromSubAccount}
        disabled={!selectedSubAccount || isLoading}
        className="px-4 py-2 bg-green-500 text-white rounded disabled:opacity-50"
      >
        {isLoading ? '전송 중...' : '서브 어카운트에서 전송'}
      </button>
    </div>
  )
}

완전한 예제

모든 서브 어카운트 기능을 결합한 완전한 컴포넌트:
import { useAccount, useConnector } from 'wagmi'
import { useState, useEffect } from 'react'

export function SubAccountManager() {
  const { address, isConnected } = useAccount()
  const connector = useConnector()
  const [subAccounts, setSubAccounts] = useState<string[]>([])
  const [isCreating, setIsCreating] = useState(false)
  const [isLoading, setIsLoading] = useState(false)

  const fetchSubAccounts = async () => {
    if (!connector || !isConnected) return

    setIsLoading(true)
    try {
      const provider = connector.provider
      const result = await provider?.request({
        method: 'wallet_getSubAccounts',
        params: [{
          version: '1.0',
          chainId: `0x${Number(8453).toString(16)}`,
          from: address,
        }]
      })

      if (result?.subAccounts) {
        setSubAccounts(result.subAccounts)
      }
    } catch (error) {
      console.error('Failed to fetch Sub Accounts:', error)
    } finally {
      setIsLoading(false)
    }
  }

  const createSubAccount = async () => {
    if (!connector || !isConnected) return

    setIsCreating(true)
    try {
      const provider = connector.provider
      const result = await provider?.request({
        method: 'wallet_addSubAccount',
        params: [{
          version: '1.0',
          chainId: `0x${Number(8453).toString(16)}`,
          from: address,
        }]
      })

      if (result?.subAccount) {
        // 목록 새로고침
        await fetchSubAccounts()
      }
    } catch (error) {
      console.error('Failed to create Sub Account:', error)
    } finally {
      setIsCreating(false)
    }
  }

  useEffect(() => {
    if (isConnected) {
      fetchSubAccounts()
    }
  }, [isConnected])

  if (!isConnected) {
    return <p>먼저 지갑을 연결해 주세요</p>
  }

  return (
    <div className="space-y-6">
      <div className="flex items-center justify-between">
        <h2 className="text-xl font-bold">서브 어카운트 관리자</h2>
        <button
          onClick={createSubAccount}
          disabled={isCreating}
          className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
        >
          {isCreating ? '생성 중...' : '서브 어카운트 생성'}
        </button>
      </div>

      <div className="space-y-4">
        <div className="flex items-center justify-between">
          <h3 className="text-lg font-semibold">내 서브 어카운트 ({subAccounts.length})</h3>
          <button
            onClick={fetchSubAccounts}
            disabled={isLoading}
            className="px-3 py-1 bg-gray-500 text-white rounded text-sm"
          >
            {isLoading ? '로딩 중...' : '새로고침'}
          </button>
        </div>

        {subAccounts.length === 0 ? (
          <p className="text-gray-500">서브 어카운트가 없습니다. 하나를 생성해서 시작하세요!</p>
        ) : (
          <div className="grid gap-3">
            {subAccounts.map((subAccount, index) => (
              <div
                key={subAccount}
                className="p-4 bg-blue-50 border border-blue-200 rounded-lg"
              >
                <div className="flex items-center justify-between">
                  <div>
                    <p className="font-mono text-sm">{subAccount}</p>
                    <p className="text-xs text-blue-600">서브 어카운트 #{index + 1}</p>
                  </div>
                </div>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  )
}

더 알아보기