import { useNeptuneStore } from '@/stores/neptuneStore' import * as API from '@/api/neptuneApi' import type { GenerateSeedResult, ViewKeyResult } from '@/interface' import initWasm, { generate_seed, get_viewkey, address_from_seed, validate_seed_phrase, } from '@neptune/wasm' let wasmInitialized = false let initPromise: Promise | null = null export function useNeptuneWallet() { const store = useNeptuneStore() // ===== WASM METHODS ===== const ensureWasmInitialized = async (): Promise => { if (wasmInitialized) { return } if (initPromise) { return initPromise } initPromise = (async () => { try { store.setLoading(true) store.setError(null) await initWasm() wasmInitialized = true } catch (err) { wasmInitialized = false const errorMsg = 'Failed to initialize Neptune WASM' store.setError(errorMsg) console.error('WASM init error:', err) throw new Error(errorMsg) } finally { store.setLoading(false) } })() return initPromise } const generateWallet = async (): Promise => { try { store.setLoading(true) store.setError(null) await ensureWasmInitialized() const resultJson = generate_seed() const result: GenerateSeedResult = JSON.parse(resultJson) store.setSeedPhrase(result.seed_phrase) store.setReceiverId(result.receiver_identifier) const viewKeyResult = await getViewKeyFromSeed(result.seed_phrase) store.setViewKey(viewKeyResult.view_key) store.setAddress(viewKeyResult.address) return result } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Failed to generate wallet' store.setError(errorMsg) throw err } finally { store.setLoading(false) } } const getViewKeyFromSeed = async (seedPhrase: string[]): Promise => { await ensureWasmInitialized() const seedPhraseJson = JSON.stringify(seedPhrase) const resultJson = get_viewkey(seedPhraseJson, store.getNetwork) return JSON.parse(resultJson) } const importWallet = async (seedPhrase: string[]): Promise => { try { store.setLoading(true) store.setError(null) const isValid = await validateSeedPhrase(seedPhrase) if (!isValid) { throw new Error('Invalid seed phrase') } const result = await getViewKeyFromSeed(seedPhrase) store.setSeedPhrase(seedPhrase) store.setReceiverId(result.receiver_identifier) store.setViewKey(result.view_key) store.setAddress(result.address) return result } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Failed to import wallet' store.setError(errorMsg) throw err } finally { store.setLoading(false) } } const getAddressFromSeed = async (seedPhrase: string[]): Promise => { await ensureWasmInitialized() const seedPhraseJson = JSON.stringify(seedPhrase) return address_from_seed(seedPhraseJson, store.getNetwork) } const validateSeedPhrase = async (seedPhrase: string[]): Promise => { try { await ensureWasmInitialized() const seedPhraseJson = JSON.stringify(seedPhrase) return validate_seed_phrase(seedPhraseJson) } catch (err) { console.error('Validation error:', err) return false } } const decryptKeystore = async (password: string): Promise => { try { const result = await (window as any).walletApi.decryptKeystore( store.getKeystorePath || '', password ) if (result.error) { console.error('Error decrypting keystore composable:', result.error) return } const seedPhrase = result.phrase.trim().split(/\s+/) const viewKeyResult = await getViewKeyFromSeed(seedPhrase) store.setSeedPhrase(seedPhrase) store.setAddress(viewKeyResult.address) store.setViewKey(viewKeyResult.view_key) store.setReceiverId(viewKeyResult.receiver_identifier) } catch (err) { console.error('Error decrypting keystore composable:', err) } } // ===== API METHODS ===== const getUtxos = async ( startBlock: number = 0, endBlock: number | null = null, maxSearchDepth: number = 1000 ): Promise => { try { if (!store.getViewKey) { throw new Error('No view key available. Please import or generate a wallet first.') } store.setLoading(true) store.setError(null) const response = await API.getUtxosFromViewKey( store.getViewKey, startBlock, endBlock, maxSearchDepth ) const result = response.data?.result || response.data store.setUtxos(result.utxos || result || []) return result } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Failed to get UTXOs' store.setError(errorMsg) throw err } finally { store.setLoading(false) } } const getBalance = async (): Promise => { try { store.setLoading(true) store.setError(null) const response = await API.getBalance() const result = response.data?.result || response.data store.setBalance(result.balance || result) return result } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Failed to get balance' store.setError(errorMsg) throw err } finally { store.setLoading(false) } } const getBlockHeight = async (): Promise => { try { store.setLoading(true) store.setError(null) const response = await API.getBlockHeight() const result = response.data?.result || response.data return result.height || result } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Failed to get block height' store.setError(errorMsg) throw err } finally { store.setLoading(false) } } const getNetworkInfo = async (): Promise => { try { store.setLoading(true) store.setError(null) const response = await API.getNetworkInfo() const result = response.data?.result || response.data return result } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Failed to get network info' store.setError(errorMsg) throw err } finally { store.setLoading(false) } } const sendTransaction = async ( toAddress: string, amount: string, fee: string ): Promise => { try { store.setLoading(true) store.setError(null) const response = await API.sendTransaction(toAddress, amount, fee) const result = response.data?.result || response.data return result } catch (err) { const errorMsg = err instanceof Error ? err.message : 'Failed to send transaction' store.setError(errorMsg) throw err } finally { store.setLoading(false) } } const setNetwork = async (network: 'mainnet' | 'testnet') => { store.setNetwork(network) if (store.getSeedPhrase) { const viewKeyResult = await getViewKeyFromSeed(store.getSeedPhrase) store.setAddress(viewKeyResult.address) store.setViewKey(viewKeyResult.view_key) } } // ===== UTILITY METHODS ===== const clearWallet = () => { store.clearWallet() } return { initWasm: ensureWasmInitialized, generateWallet, importWallet, getViewKeyFromSeed, getAddressFromSeed, validateSeedPhrase, getUtxos, getBalance, getBlockHeight, getNetworkInfo, sendTransaction, decryptKeystore, clearWallet, setNetwork, } }