본문으로 건너뛰기

Wallet Management

이 가이드에서는 GIWA SDK의 지갑 생성, 복구 및 관리 기능에 대해 설명합니다.

useGiwaWallet Hook

import { useGiwaWallet } from 'giwa-react-native-wallet';

function WalletScreen() {
const {
wallet, // Current wallet information
isLoading, // Loading state
error, // Error information
createWallet, // Create new wallet
recoverWallet, // Recover with mnemonic
importPrivateKey, // Import with private key
exportPrivateKey, // Export private key
disconnect, // Disconnect wallet
} = useGiwaWallet();

// ...
}

Create New Wallet

const handleCreate = async () => {
try {
const { wallet, mnemonic } = await createWallet();

console.log('Address:', wallet.address);
console.log('Mnemonic:', mnemonic); // 12-word recovery phrase

// Important: Show the mnemonic to the user and guide them to back it up safely
// The mnemonic is displayed only once and is not stored within the SDK
} catch (error) {
console.error('Wallet creation failed:', error.message);
}
};
Mnemonic Security

니모닉(복구 문구)은 지갑 생성 시 한 번만 반환됩니다. SDK에서 니모닉을 저장하지 않으므로 사용자가 안전한 곳에 백업하도록 반드시 안내해야 합니다.

Wallet Recovery

Recover with Mnemonic

const handleRecover = async () => {
const mnemonic = 'apple banana cherry ...'; // 12 words

try {
const wallet = await recoverWallet(mnemonic);
console.log('Recovered address:', wallet.address);
} catch (error) {
if (error.code === 'INVALID_MNEMONIC') {
Alert.alert('Error', 'Invalid recovery phrase');
}
}
};

Import with Private Key

const handleImport = async () => {
const privateKey = '0x...'; // 64-character hex string

try {
const wallet = await importPrivateKey(privateKey);
console.log('Imported address:', wallet.address);
} catch (error) {
Alert.alert('Error', 'Invalid private key');
}
};

Export Private Key

Warning

프라이빗 키 내보내기는 민감한 작업입니다. 반드시 생체 인증이나 추가 확인 절차를 거쳐야 합니다.

const handleExport = async () => {
try {
// Biometric authentication is automatically requested if configured
const privateKey = await exportPrivateKey();

// Display private key securely (consider using a modal with auto-dismiss)
Alert.alert(
'Private Key',
privateKey,
[{ text: 'OK' }],
{ cancelable: false }
);
} catch (error) {
if (error.code === 'BIOMETRIC_FAILED') {
Alert.alert('Authentication Failed', 'Biometric authentication failed');
}
}
};

Disconnect Wallet

const handleDisconnect = async () => {
Alert.alert(
'Disconnect Wallet',
'Are you sure you want to disconnect? You cannot recover the wallet without the recovery phrase.',
[
{ text: 'Cancel', style: 'cancel' },
{
text: 'Disconnect',
style: 'destructive',
onPress: async () => {
await disconnect();
},
},
]
);
};

Check Wallet Status

function WalletStatus() {
const { wallet, isLoading, error } = useGiwaWallet();

if (isLoading) {
return <ActivityIndicator />;
}

if (error) {
return <Text>Error: {error.message}</Text>;
}

if (!wallet) {
return <Text>No wallet connected</Text>;
}

return (
<View>
<Text>Address: {wallet.address}</Text>
<Text>Connected: {wallet.isConnected ? 'Yes' : 'No'}</Text>
</View>
);
}

Complete Example

import { useState } from 'react';
import { View, Text, Button, TextInput, Alert } from 'react-native';
import { useGiwaWallet } from 'giwa-react-native-wallet';

export function WalletManager() {
const {
wallet,
createWallet,
recoverWallet,
exportPrivateKey,
disconnect,
isLoading,
} = useGiwaWallet();

const [mnemonicInput, setMnemonicInput] = useState('');
const [showRecover, setShowRecover] = useState(false);

if (wallet) {
return (
<View style={{ padding: 20 }}>
<Text style={{ fontSize: 16, marginBottom: 10 }}>Wallet Connected</Text>
<Text selectable style={{ fontFamily: 'monospace', marginBottom: 20 }}>
{wallet.address}
</Text>

<Button title="Export Private Key" onPress={exportPrivateKey} />
<Button title="Disconnect" onPress={disconnect} color="red" />
</View>
);
}

return (
<View style={{ padding: 20 }}>
<Button
title="Create New Wallet"
onPress={async () => {
const { mnemonic } = await createWallet();
Alert.alert('Backup Required', `Recovery phrase:\n\n${mnemonic}`);
}}
disabled={isLoading}
/>

<Button
title="Recover Existing Wallet"
onPress={() => setShowRecover(!showRecover)}
/>

{showRecover && (
<>
<TextInput
placeholder="Enter 12-word recovery phrase"
value={mnemonicInput}
onChangeText={setMnemonicInput}
multiline
style={{
borderWidth: 1,
borderColor: '#ccc',
padding: 10,
marginVertical: 10,
}}
/>
<Button
title="Recover"
onPress={() => recoverWallet(mnemonicInput)}
disabled={isLoading || !mnemonicInput}
/>
</>
)}
</View>
);
}

Next Steps