native ui + touch id unlock + portfolio dashboard

This commit is contained in:
2026-08-01 19:07:49 +08:00
parent 42a22918a3
commit bd8ba8e3e5
18 changed files with 675 additions and 194 deletions
@@ -246,6 +246,22 @@ export const MoneroWallet = () => {
await refresh()
}
const autoUnlock = async (name?: string) => {
if (!electrobun.rpc) return false
const target = name ?? wallets[0]
if (!target) return false
const pw = await moneroGetStoredPassword(target)
if (!pw) return false
await electrobun.rpc.request.moneroOpenWallet({
name: target,
password: pw,
})
walletName = target
walletOpen = true
await refresh()
return true
}
const refresh = async () => {
if (!electrobun.rpc) return
loading = true
@@ -430,6 +446,7 @@ export const MoneroWallet = () => {
createWallet,
restoreWallet,
openWallet,
autoUnlock,
refresh,
send,
sendAll,
@@ -0,0 +1,59 @@
import { electrobun } from '$lib/electrobun'
let unlocked = $state(false)
let biometricAvailable = $state(false)
let unlocking = $state(false)
let error = $state('')
const checkBiometric = async () => {
if (!electrobun.rpc) return
try {
biometricAvailable = await electrobun.rpc.request.biometricCanAuth({})
} catch { /* ignore */ }
}
const unlock = async (): Promise<boolean> => {
if (!electrobun.rpc) return false
unlocking = true
error = ''
try {
const ok = await electrobun.rpc.request.biometricAuth({
reason: 'Unlock Koins',
})
if (ok) {
unlocked = true
} else {
error = 'Authentication failed'
}
return ok
} catch (e) {
error = e instanceof Error ? e.message : 'Unlock failed'
return false
} finally {
unlocking = false
}
}
const lock = () => {
unlocked = false
error = ''
}
checkBiometric()
export const session = {
get unlocked() {
return unlocked
},
get biometricAvailable() {
return biometricAvailable
},
get unlocking() {
return unlocking
},
get error() {
return error
},
unlock,
lock,
}
@@ -179,6 +179,28 @@ export const XrpWallet = () => {
return false
}
const autoUnlock = async (walletId?: string) => {
const id = walletId ?? currentWalletId ?? wallets[0]?.id
if (!id) return false
currentWalletId = id
const wallet = wallets.find((w) => w.id === id)
if (!wallet) return false
if (electrobun.rpc && wallet.hasPassword) {
const [ph] = await tryCatch(
electrobun.rpc.request.getSecret({
service: 'koins',
name: `xrp_auth_${id}`,
}),
)
if (ph) currentPasswordHash = ph
} else {
currentPasswordHash = null
}
const ok = await loadSeedForWallet(id)
if (ok) accountType = 'xrp'
return ok
}
const saveWallet = async (
kind: 'create' | 'import',
name: string,
@@ -412,6 +434,7 @@ export const XrpWallet = () => {
hashPassword,
selectWallet,
selectAndUnlockWallet,
autoUnlock,
loadSeedForWallet,
deleteWallet,
clearSelection,