feat(storage): save HD to ~/.wallet-generator/hdwallet and single to ~/.wallet-generator/single

This commit is contained in:
2026-03-09 15:34:56 +01:00
parent c7ad9d114d
commit aad81e1cf3
4 changed files with 21 additions and 12 deletions

View File

@@ -10,10 +10,19 @@ const VITE_PORT = 5173
let mainWindow = null
// ── Wallet storage directory ───────────────────────────────────────────────────
const WALLET_DIR = path.join(os.homedir(), '.wallet-generator', 'wallet')
const WALLET_ROOT_DIR = path.join(os.homedir(), '.wallet-generator')
const WALLET_DIRS = {
hd: path.join(WALLET_ROOT_DIR, 'hdwallet'),
single: path.join(WALLET_ROOT_DIR, 'single'),
}
function ensureWalletDir() {
fs.mkdirSync(WALLET_DIR, { recursive: true })
function ensureWalletDir(kind) {
const walletDir = WALLET_DIRS[kind]
if (!walletDir) {
throw new Error(`Unsupported wallet kind: '${kind}'. Use 'hd' or 'single'.`)
}
fs.mkdirSync(walletDir, { recursive: true })
return walletDir
}
// ── Resolve Python executable ──────────────────────────────────────────────────
@@ -54,16 +63,16 @@ ipcMain.handle('p2wpkh', (_, args) => callPython('p2wpkh', args))
ipcMain.handle('p2tr', (_, args) => callPython('p2tr', args))
ipcMain.handle('single-encrypt', (_, args) => callPython('single_encrypt', args))
ipcMain.handle('save-wallet', (_, { filename, data }) => {
ensureWalletDir()
const filePath = path.join(WALLET_DIR, filename)
ipcMain.handle('save-wallet', (_, { filename, data, kind }) => {
const walletDir = ensureWalletDir(kind)
const filePath = path.join(walletDir, filename)
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8')
return filePath
})
ipcMain.handle('get-wallet-dir', () => {
ensureWalletDir()
return WALLET_DIR
fs.mkdirSync(WALLET_ROOT_DIR, { recursive: true })
return WALLET_ROOT_DIR
})
// ── Create window ──────────────────────────────────────────────────────────────

View File

@@ -10,6 +10,6 @@ contextBridge.exposeInMainWorld('electronAPI', {
p2wpkh: (args) => ipcRenderer.invoke('p2wpkh', args),
p2tr: (args) => ipcRenderer.invoke('p2tr', args),
singleEncrypt:(args) => ipcRenderer.invoke('single-encrypt', args),
saveWallet: (filename, data) => ipcRenderer.invoke('save-wallet', { filename, data }),
saveWallet: (filename, data, kind) => ipcRenderer.invoke('save-wallet', { filename, data, kind }),
getWalletDir: () => ipcRenderer.invoke('get-wallet-dir'),
})

View File

@@ -52,7 +52,7 @@ export default function HDWallet() {
data = await window.electronAPI.hdEncrypt({ wallet, password: savePassword })
}
const filename = `wallet_${form.network}_${form.bip_type}_${Date.now()}.json`
const savedPath = await window.electronAPI.saveWallet(filename, data)
const savedPath = await window.electronAPI.saveWallet(filename, data, 'hd')
const encrypted = savePassword ? ' (encrypted)' : ''
setSaveMsg(`Saved${encrypted}: ${savedPath}`)
} catch (e) {

View File

@@ -60,7 +60,7 @@ export default function SingleAddress({ initialTab = 'p2pkh' }) {
data = await window.electronAPI.singleEncrypt({ wallet: result, password: savePassword })
}
const name = filename.trim().endsWith('.json') ? filename.trim() : `${filename.trim()}.json`
const savedPath = await window.electronAPI.saveWallet(name, data)
const savedPath = await window.electronAPI.saveWallet(name, data, 'single')
setSaveMsg(savePassword.trim() ? `Saved (encrypted): ${savedPath}` : `Saved: ${savedPath}`)
} catch (e) {
setSaveMsg('Error: ' + e.message)
@@ -141,7 +141,7 @@ export default function SingleAddress({ initialTab = 'p2pkh' }) {
value={filename}
onChange={e => setFilename(e.target.value)}
/>
<span className="form-hint">.json · saved to ~/.wallet-generator/wallet/</span>
<span className="form-hint">.json · saved to ~/.wallet-generator/single/</span>
</div>
<div className="form-group">
<label className="form-label">Encryption password (optional)</label>