Files
brk/website_next/wallets/vault/index.js
T
2026-06-22 16:42:14 +02:00

193 lines
4.0 KiB
JavaScript

import { vaultStorage } from "./storage.js";
import { createRuntime } from "./runtime.js";
/**
* @typedef {import("./storage.js").StoredWallet} StoredWallet
* @typedef {import("./storage.js").AddWalletInput} AddWalletInput
* @typedef {ReturnType<typeof createRuntime>} WalletRuntime
*/
export function createVault() {
/** @type {StoredWallet[]} */
let wallets = [];
let selectedId = "";
let locked = hasVault();
let password = "";
let ephemeral = false;
/** @type {Map<string, WalletRuntime>} */
const runtimes = new Map();
function hasVault() {
return vaultStorage.has();
}
function syncSelected() {
selectedId = wallets.some((wallet) => wallet.id === selectedId)
? selectedId
: wallets[0]?.id ?? "";
}
function clear() {
wallets = [];
selectedId = "";
runtimes.clear();
}
/**
* @returns {StoredWallet | undefined}
*/
function selectedWallet() {
return wallets.find((wallet) => wallet.id === selectedId);
}
/**
* @returns {{ wallet: StoredWallet, runtime: WalletRuntime } | undefined}
*/
function current() {
const wallet = selectedWallet();
const runtime = wallet ? runtimes.get(wallet.id) : undefined;
return wallet && runtime ? { wallet, runtime } : undefined;
}
/**
* @param {StoredWallet} wallet
* @param {WalletRuntime} runtime
*/
function isCurrent(wallet, runtime) {
return runtimes.get(wallet.id) === runtime;
}
/**
* @param {string} walletId
*/
function select(walletId) {
selectedId = walletId;
syncSelected();
}
function lock() {
clear();
password = "";
ephemeral = false;
locked = hasVault();
}
function reset() {
vaultStorage.reset();
clear();
password = "";
ephemeral = false;
locked = false;
}
function startEphemeral() {
clear();
password = "";
ephemeral = true;
locked = false;
}
function clearEphemeral() {
clear();
password = "";
ephemeral = false;
locked = hasVault();
}
/**
* @param {string} pagePassword
*/
async function setup(pagePassword) {
await vaultStorage.setup(pagePassword);
clear();
password = pagePassword;
ephemeral = false;
locked = false;
}
/**
* @param {string} pagePassword
*/
async function unlock(pagePassword) {
wallets = await vaultStorage.load(pagePassword);
syncSelected();
runtimes.clear();
password = pagePassword;
ephemeral = false;
locked = false;
for (const wallet of wallets) {
runtimes.set(wallet.id, createRuntime(wallet.source));
}
}
/**
* @param {AddWalletInput} input
*/
async function addWallet(input) {
if (ephemeral) {
const wallet = vaultStorage.createWallet(input);
wallets = [...wallets, wallet];
selectedId = wallet.id;
locked = false;
runtimes.set(wallet.id, createRuntime(wallet.source));
return;
}
const added = await vaultStorage.addWallet(wallets, input, password);
wallets = added.wallets;
selectedId = added.wallet.id;
locked = false;
runtimes.set(added.wallet.id, createRuntime(added.wallet.source));
}
/**
* @param {string} walletId
*/
async function deleteWallet(walletId) {
if (ephemeral) {
wallets = wallets.filter((wallet) => wallet.id !== walletId);
} else {
wallets = await vaultStorage.deleteWallet(wallets, walletId, password);
}
runtimes.delete(walletId);
syncSelected();
}
return {
get wallets() {
return wallets;
},
get selectedId() {
return selectedId;
},
get hasPassword() {
return password !== "";
},
needsSetup() {
return !hasVault() && !password && !ephemeral;
},
isLocked() {
return !ephemeral && locked && hasVault();
},
isEphemeral() {
return ephemeral;
},
current,
isCurrent,
select,
lock,
reset,
startEphemeral,
clearEphemeral,
setup,
unlock,
addWallet,
deleteWallet,
};
}