diff --git a/electron/ipcHandlers.ts b/electron/ipcHandlers.ts index 4ea0842..6a8b9e3 100644 --- a/electron/ipcHandlers.ts +++ b/electron/ipcHandlers.ts @@ -2,6 +2,7 @@ import { ipcMain, dialog, app } from 'electron' import fs from 'fs' import path from 'path' import { encrypt, fromEncryptedJson } from './utils/keystore' +import logger from './logger' const neptuneNative = require('@neptune/native') @@ -13,15 +14,14 @@ ipcMain.handle('wallet:createKeystore', async (_event, seed, password) => { const savePath = path.join(process.cwd(), 'wallets') fs.mkdirSync(savePath, { recursive: true }) - // Use timestamp for filename const timestamp = Date.now() const fileName = `neptune-wallet-${timestamp}.json` const filePath = path.join(savePath, fileName) fs.writeFileSync(filePath, keystore) return { filePath } - } catch (error) { - console.error('Error creating keystore:', error) + } catch (error: any) { + logger.error('Error creating keystore:', error.message) throw error } }) @@ -46,8 +46,8 @@ ipcMain.handle('wallet:saveKeystoreAs', async (_event, seed: string, password: s fs.writeFileSync(filePath, keystore) return { filePath } - } catch (error) { - console.error('Error saving keystore (Save As):', error) + } catch (error: any) { + logger.error('Error saving keystore (Save As):', error.message) throw error } }) @@ -58,8 +58,8 @@ ipcMain.handle('wallet:decryptKeystore', async (_event, filePath, password) => { const phrase = await fromEncryptedJson(json, password) return { phrase } - } catch (error) { - console.error('Error decrypting keystore ipc:', error) + } catch (error: any) { + logger.error('Error decrypting keystore ipc:', error.message) throw error } }) @@ -91,14 +91,14 @@ ipcMain.handle('wallet:checkKeystore', async () => { if (typeof height === 'number' && Number.isFinite(height)) { minBlockHeight = height } - } catch (error) { - console.warn('Unable to read minBlockHeight from keystore:', error) + } catch (error: any) { + logger.warn('Unable to read minBlockHeight from keystore:', error.message) } return { exists: true, filePath: resolvedPath, minBlockHeight } - } catch (error) { - console.error('Error checking keystore ipc:', error) - return { exists: false, filePath: null, minBlockHeight: null, error: String(error) } + } catch (error: any) { + logger.error('Error checking keystore ipc:', error.message) + return { exists: false, filePath: null, minBlockHeight: null, error: error.message } } }) @@ -130,9 +130,9 @@ ipcMain.handle( fs.writeFileSync(normalizedPath, JSON.stringify(walletJson, null, 2), 'utf-8') return { success: true, minBlockHeight } - } catch (error) { - console.error('Error updating min block height:', error) - return { success: false, error: String(error) } + } catch (error: any) { + logger.error('Error updating min block height:', error.message) + return { success: false, error: error.message } } } ) @@ -162,9 +162,9 @@ ipcMain.handle( } return { success: true, minBlockHeight: null } - } catch (error) { - console.error('Error reading min block height:', error) - return { success: false, error: String(error), minBlockHeight: null } + } catch (error: any) { + logger.error('Error reading min block height:', error.message) + return { success: false, error: error.message, minBlockHeight: null } } } ) @@ -173,8 +173,8 @@ ipcMain.handle('wallet:generateKeysFromSeed', async (_event, seedPhrase: string[ try { const wallet = new neptuneNative.WalletManager() return wallet.generateKeysFromSeed(seedPhrase) - } catch (error) { - console.error('Error generating keys from seed ipc:', error) + } catch (error: any) { + logger.error('Error generating keys from seed ipc:', error.message) throw error } }) @@ -188,7 +188,6 @@ ipcMain.handle('wallet:buildTransaction', async (_event, args) => { import.meta.env.VITE_APP_API, spendingKeyHex, inputAdditionRecords, - // pass minBlockHeight from args if provided, default 0 typeof args?.minBlockHeight === 'number' && Number.isFinite(args.minBlockHeight) ? args.minBlockHeight : 0, @@ -197,8 +196,12 @@ ipcMain.handle('wallet:buildTransaction', async (_event, args) => { fee ) return JSON.parse(result) - } catch (error) { - console.error('Error building transaction with primitive proof ipc:', error) + } catch (error: any) { + logger.error('Error building transaction with primitive proof ipc:', error.message) throw error } }) + +ipcMain.on('log:info', (_, msg: string) => logger.info(msg)) +ipcMain.on('log:warn', (_, msg: string) => logger.warn(msg)) +ipcMain.on('log:error', (_, msg: string) => logger.error(msg)) diff --git a/electron/logger.ts b/electron/logger.ts new file mode 100644 index 0000000..e8298af --- /dev/null +++ b/electron/logger.ts @@ -0,0 +1,33 @@ +import { app } from 'electron' +import log from 'electron-log' + +const isDev = app.isPackaged + +console.log('isDev :>> ', isDev); + +if (!isDev) { + log.transports.file.level = 'info' + log.transports.console.level = false + log.transports.file.format = '{y}-{m}-{d} {h}:{i}:{s} [{level}] {text}' +} + +export const logger = { + info: (...args: any[]) => { + if (isDev) console.log('[INFO]', ...args) + else log.info(...args) + }, + warn: (...args: any[]) => { + if (isDev) console.warn('[WARN]', ...args) + else log.warn(...args) + }, + error: (...args: any[]) => { + if (isDev) console.error('[ERROR]', ...args) + else log.error(...args) + }, + debug: (...args: any[]) => { + if (isDev) console.debug('[DEBUG]', ...args) + else log.debug(...args) + }, +} + +export default logger diff --git a/electron/main.ts b/electron/main.ts index 94e4a3b..1ece828 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -2,12 +2,14 @@ import { app, BrowserWindow } from 'electron' import path from 'node:path' import started from 'electron-squirrel-startup' import './ipcHandlers' +import logger from './logger' if (started) { app.quit() } const createWindow = () => { + logger.info('App started') const mainWindow = new BrowserWindow({ width: 800, height: 800, @@ -38,6 +40,7 @@ app.on('ready', createWindow) // for applications and their menu bar to stay active until the user quits // explicitly with Cmd + Q. app.on('window-all-closed', () => { + logger.info('App closed') if (process.platform !== 'darwin') { app.quit() } diff --git a/electron/preload.ts b/electron/preload.ts index 817977c..4e332b8 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -18,3 +18,9 @@ contextBridge.exposeInMainWorld('walletApi', { getMinBlockHeight: (filePath: string | null) => ipcRenderer.invoke('wallet:getMinBlockHeight', filePath), }) + +contextBridge.exposeInMainWorld('logger', { + info: (msg: string) => ipcRenderer.send('log:info', msg), + warn: (msg: string) => ipcRenderer.send('log:warn', msg), + error: (msg: string) => ipcRenderer.send('log:error', msg), +}) diff --git a/package-lock.json b/package-lock.json index c6468a6..70e1f78 100644 --- a/package-lock.json +++ b/package-lock.json @@ -16,6 +16,7 @@ "ant-design-vue": "^4.2.6", "axios": "^1.6.8", "crypto": "^1.0.1", + "electron-log": "^5.4.3", "electron-squirrel-startup": "^1.0.1", "pinia": "^2.1.7", "vue": "^3.4.21", @@ -5807,6 +5808,15 @@ "node": ">=10" } }, + "node_modules/electron-log": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-5.4.3.tgz", + "integrity": "sha512-sOUsM3LjZdugatazSQ/XTyNcw8dfvH1SYhXWiJyfYodAAKOZdHs0txPiLDXFzOZbhXgAgshQkshH2ccq0feyLQ==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, "node_modules/electron-squirrel-startup": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/electron-squirrel-startup/-/electron-squirrel-startup-1.0.1.tgz", diff --git a/package.json b/package.json index ec4a366..f364fef 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "ant-design-vue": "^4.2.6", "axios": "^1.6.8", "crypto": "^1.0.1", + "electron-log": "^5.4.3", "electron-squirrel-startup": "^1.0.1", "pinia": "^2.1.7", "vue": "^3.4.21", diff --git a/src/composables/useNeptuneWallet.ts b/src/composables/useNeptuneWallet.ts index dc7669a..94eec43 100644 --- a/src/composables/useNeptuneWallet.ts +++ b/src/composables/useNeptuneWallet.ts @@ -30,11 +30,10 @@ export function useNeptuneWallet() { await initWasm() wasmInitialized = true - } catch (err) { + } catch (err: any) { wasmInitialized = false - const errorMsg = 'Failed to initialize Neptune WASM' - console.error('WASM init error:', err) - throw new Error(errorMsg) + await (window as any).logger.error('WASM init error:', err.message) + throw new Error('Failed to initialize Neptune WASM') } })() @@ -59,8 +58,8 @@ export function useNeptuneWallet() { store.setAddress(addressResult) return result - } catch (err) { - console.error('Error generating wallet:', err) + } catch (err: any) { + await (window as any).logger.error('Error generating wallet:', err.message) throw err } } @@ -93,8 +92,8 @@ export function useNeptuneWallet() { spendingKey: result.spending_key_hex, address: addressResult, } - } catch (err) { - console.error('Error recovering wallet from seed:', err) + } catch (err: any) { + await (window as any).logger.error('Error recovering wallet from seed:', err.message) throw err } } @@ -128,14 +127,14 @@ export function useNeptuneWallet() { store.setAddress(addressResult) await loadMinBlockHeightFromKeystore() - } catch (err) { + } catch (err: any) { if ( err instanceof Error && (err.message.includes('Unsupported state') || err.message.includes('unable to authenticate')) ) { - console.error('Invalid password') - } else console.error('Error decrypting keystore:', err) + await (window as any).logger.error('Invalid password') + } else await (window as any).logger.error('Error decrypting keystore:', err.message) throw err } @@ -147,8 +146,8 @@ export function useNeptuneWallet() { store.setKeystorePath(result.filePath) store.setMinBlockHeight(null) return result.filePath - } catch (err) { - console.error('Error creating keystore:', err) + } catch (err: any) { + await (window as any).logger.error('Error creating keystore:', err.message) throw err } } @@ -158,8 +157,8 @@ export function useNeptuneWallet() { const result = await (window as any).walletApi.saveKeystoreAs(seed, password) if (!result.filePath) throw new Error('User canceled') return result.filePath - } catch (err) { - console.error('Error saving keystore:', err) + } catch (err: any) { + await (window as any).logger.error('Error saving keystore:', err.message) throw err } } @@ -175,8 +174,8 @@ export function useNeptuneWallet() { store.setMinBlockHeight(toFiniteNumber(height)) } return true - } catch (err) { - console.error('Error checking keystore:', err) + } catch (err: any) { + await (window as any).logger.error('Error checking keystore:', err.message) throw err } } @@ -202,8 +201,8 @@ export function useNeptuneWallet() { ) if (!response.success) throw new Error('Failed to update min block height') store.setMinBlockHeight(minBlockHeight) - } catch (err) { - console.error('Error saving min block height:', err) + } catch (err: any) { + await (window as any).logger.error('Error saving min block height:', err.message) throw err } } @@ -220,8 +219,8 @@ export function useNeptuneWallet() { store.setMinBlockHeight(minBlockHeight) return minBlockHeight - } catch (err) { - console.error('Error loading min block height:', err) + } catch (err: any) { + await (window as any).logger.error('Error loading min block height:', err.message) throw err } } @@ -249,8 +248,8 @@ export function useNeptuneWallet() { await persistMinBlockHeight(utxoList) return result - } catch (err) { - console.error('Error getting UTXOs:', err) + } catch (err: any) { + await (window as any).logger.error('Error getting UTXOs:', err.message) throw err } } @@ -275,8 +274,8 @@ export function useNeptuneWallet() { balance: result?.balance || result, pendingBalance: result?.pendingBalance || result, } - } catch (err) { - console.error('Error getting balance:', err) + } catch (err: any) { + await (window as any).logger.error('Error getting balance:', err.message) throw err } } @@ -286,8 +285,8 @@ export function useNeptuneWallet() { const response = await API.getBlockHeight() const result = response?.result || response return result?.height || result - } catch (err) { - console.error('Error getting block height:', err) + } catch (err: any) { + await (window as any).logger.error('Error getting block height:', err.message) throw err } } @@ -299,8 +298,8 @@ export function useNeptuneWallet() { store.setNetwork((result.network + 'net') as 'mainnet' | 'testnet') return result - } catch (err) { - console.error('Error getting network info:', err) + } catch (err: any) { + await (window as any).logger.error('Error getting network info:', err.message) throw err } } @@ -327,8 +326,8 @@ export function useNeptuneWallet() { const response = await API.broadcastSignedTransaction(transactionHex) const result = response?.result || response return result - } catch (err) { - console.error('Error sending transaction:', err) + } catch (err: any) { + await (window as any).logger.error('Error sending transaction:', err.message) throw err } } @@ -345,8 +344,8 @@ export function useNeptuneWallet() { const addressResult = await getAddressFromSeed(store.getSeedPhrase) store.setAddress(addressResult) } - } catch (err) { - console.error('Error setting network:', err) + } catch (err: any) { + await (window as any).logger.error('Error setting network:', err.message) throw err } } diff --git a/src/views/Home/components/UTXOTab.vue b/src/views/Home/components/UTXOTab.vue index 67a1e86..30d5289 100644 --- a/src/views/Home/components/UTXOTab.vue +++ b/src/views/Home/components/UTXOTab.vue @@ -32,7 +32,6 @@ const loadUtxos = async () => { loading.value = true const result = await getUtxos() if (result.error) { - console.error(result.error.message) message.error('Failed to load UTXOs') loading.value = false return @@ -40,7 +39,6 @@ const loadUtxos = async () => { loading.value = false } catch (err) { message.error('Failed to load UTXOs') - console.error('Error loading UTXOs:', err) } finally { loading.value = false } @@ -63,8 +61,8 @@ watch(

IN USE UTXOS

-

COUNT {{ inUseUtxosCount }}

-

AMOUNT {{ inUseUtxosAmount }} NPT

+

COUNT {{ inUseUtxosCount }}

+

AMOUNT {{ inUseUtxosAmount }} NPT

@@ -116,6 +114,10 @@ watch( font-weight: var(--font-bold); margin-right: var(--spacing-sm); } + + strong { + color: var(--primary-color); + } } } } diff --git a/src/views/Home/components/wallet-tab/SendTransactionComponent.vue b/src/views/Home/components/wallet-tab/SendTransactionComponent.vue index d874995..32fbc88 100644 --- a/src/views/Home/components/wallet-tab/SendTransactionComponent.vue +++ b/src/views/Home/components/wallet-tab/SendTransactionComponent.vue @@ -158,9 +158,11 @@ const displayAddress = computed(() => {
-