import React, { useState } from 'react';
import { useWallets, useBaseAccountSdk, toViemAccount } from '@privy-io/react-auth';
import { toHex } from 'viem';
export function SubAccountDemo() {
const [subAccount, setSubAccount] = useState(null);
const [isLoading, setIsLoading] = useState(false);
const [message, setMessage] = useState('');
const [signature, setSignature] = useState('');
const { wallets } = useWallets();
const { baseAccountSdk } = useBaseAccountSdk();
const embeddedWallet = wallets.find((wallet) => wallet.walletClientType === 'privy');
const baseAccount = wallets.find((wallet) => wallet.walletClientType === 'base_account');
const setupSubAccount = async () => {
if (!embeddedWallet || !baseAccount || !baseAccountSdk) return;
setIsLoading(true);
try {
await baseAccount.switchChain(84532); // Base Sepolia
const provider = await baseAccount.getEthereumProvider();
// Get or create Sub Account
const { subAccounts: [existingSubAccount] } = await provider.request({
method: 'wallet_getSubAccounts',
params: [{
account: baseAccount.address,
domain: window.location.origin
}]
});
const subaccount = existingSubAccount || await provider.request({
method: 'wallet_addSubAccount',
params: [{
version: '1',
account: {
type: 'create',
keys: [{
type: 'address',
publicKey: embeddedWallet.address
}]
}
}]
});
// Configure embedded wallet as owner
const toOwnerAccount = async () => {
const account = await toViemAccount({ wallet: embeddedWallet });
return { account };
};
baseAccountSdk.subAccount.setToOwnerAccount(toOwnerAccount);
setSubAccount(subaccount);
} catch (error) {
console.error('Sub Account setup failed:', error);
} finally {
setIsLoading(false);
}
};
const signMessage = async () => {
if (!baseAccount || !subAccount) return;
try {
const provider = await baseAccount.getEthereumProvider();
const sig = await provider.request({
method: 'personal_sign',
params: [toHex(message), subAccount.address]
});
setSignature(sig);
} catch (error) {
console.error('Signing failed:', error);
}
};
return (
<div className="space-y-6">
<h2 className="text-2xl font-bold">Base Sub Account Demo</h2>
{!subAccount ? (
<div>
<p className="mb-4">Set up a Sub Account for gasless interactions</p>
<button
onClick={setupSubAccount}
disabled={isLoading || !embeddedWallet || !baseAccount}
className="px-4 py-2 bg-blue-500 text-white rounded disabled:opacity-50"
>
{isLoading ? 'Setting up...' : 'Create Sub Account'}
</button>
</div>
) : (
<div className="space-y-4">
<div className="p-4 bg-green-50 border border-green-200 rounded">
<h3 className="font-semibold">Sub Account Ready</h3>
<p className="text-sm text-gray-600">Address: {subAccount.address}</p>
</div>
<div>
<label className="block mb-2">Message to sign:</label>
<input
type="text"
value={message}
onChange={(e) => setMessage(e.target.value)}
className="w-full p-2 border rounded"
placeholder="Enter message to sign"
/>
<button
onClick={signMessage}
disabled={!message}
className="mt-2 px-4 py-2 bg-green-500 text-white rounded disabled:opacity-50"
>
Sign Message
</button>
</div>
{signature && (
<div className="p-4 bg-gray-50 border rounded">
<h4 className="font-semibold mb-2">Signature:</h4>
<p className="text-sm font-mono break-all">{signature}</p>
</div>
)}
</div>
)}
</div>
);
}