Wagmi 훅과 Base Account 프로바이더 메서드를 사용하여 서브 어카운트를 생성하고 관리하는 방법을 알아보세요.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.
사전 요구 사항
다음이 완료되어 있는지 확인하세요:개요
서브 어카운트를 통해 스펜드 퍼미션을 사용하여 상위 계정의 잔액을 사용할 수 있는 자식 계정을 생성할 수 있습니다. 이를 통해 빈번한 사용자 서명의 필요성을 줄이고 사용자 경험을 향상시킵니다.서브 어카운트 생성
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>
)
}