Persist wallet state to extension storage
All checks were successful
check / check (push) Successful in 12s

State (wallets, RPC URL, setup flag) is saved to
browser.storage.local / chrome.storage.local after every
mutation and loaded on popup open. In DEBUG mode, the lock
screen is skipped since encryption is not yet implemented.
This commit is contained in:
2026-02-25 16:02:33 +07:00
parent 079541e84b
commit 88f57263fb

View File

@@ -28,21 +28,52 @@ function showView(name) {
}
}
// -- mock state (will be replaced by background messaging) --
// Browser-agnostic storage API
const storage =
typeof browser !== "undefined"
? browser.storage.local
: chrome.storage.local;
// A wallet is either { type: "hd", name, mnemonic, addresses: [...] }
// or { type: "key", name, privateKey, addresses: [single] }.
// Each address is { address, balance, tokens: [...] }.
const state = {
locked: true,
const DEFAULT_STATE = {
hasWallet: false,
password: null,
wallets: [],
selectedWallet: null,
selectedAddress: null,
rpcUrl: "https://eth.llamarpc.com",
isFirstSetup: true,
};
// Transient state (not persisted)
const state = {
...DEFAULT_STATE,
locked: true,
password: null,
selectedWallet: null,
selectedAddress: null,
};
async function saveState() {
const persisted = {
hasWallet: state.hasWallet,
wallets: state.wallets,
rpcUrl: state.rpcUrl,
isFirstSetup: state.isFirstSetup,
};
await storage.set({ autistmask: persisted });
}
async function loadState() {
const result = await storage.get("autistmask");
if (result.autistmask) {
const saved = result.autistmask;
state.hasWallet = saved.hasWallet;
state.wallets = saved.wallets || [];
state.rpcUrl = saved.rpcUrl || DEFAULT_STATE.rpcUrl;
state.isFirstSetup = saved.isFirstSetup;
}
}
// -- helpers --
function $(id) {
return document.getElementById(id);
@@ -121,11 +152,12 @@ function renderWalletList() {
});
container.querySelectorAll(".btn-add-address").forEach((btn) => {
btn.addEventListener("click", (e) => {
btn.addEventListener("click", async (e) => {
e.stopPropagation();
const wi = parseInt(btn.dataset.wallet, 10);
// TODO: derive next address from seed via background
state.wallets[wi].addresses.push(makeStubAddress());
await saveState();
renderWalletList();
});
});
@@ -180,10 +212,11 @@ function currentAddress() {
return state.wallets[state.selectedWallet].addresses[state.selectedAddress];
}
function addWalletAndGoToMain(wallet) {
async function addWalletAndGoToMain(wallet) {
state.wallets.push(wallet);
state.hasWallet = true;
state.isFirstSetup = false;
await saveState();
renderWalletList();
showView("main");
}
@@ -243,7 +276,7 @@ function backFromWalletAdd() {
}
// -- init --
function init() {
async function init() {
if (DEBUG) {
const banner = document.createElement("div");
banner.textContent = "DEBUG / INSECURE";
@@ -252,6 +285,13 @@ function init() {
document.body.prepend(banner);
}
await loadState();
// In DEBUG mode, skip the lock screen (no encryption yet)
if (DEBUG && state.hasWallet) {
state.locked = false;
}
if (!state.hasWallet) {
showView("welcome");
} else if (state.locked) {
@@ -443,7 +483,7 @@ function init() {
});
// -- Add Token --
$("btn-add-token-confirm").addEventListener("click", () => {
$("btn-add-token-confirm").addEventListener("click", async () => {
const contractAddr = $("add-token-address").value.trim();
if (!contractAddr || !contractAddr.startsWith("0x")) {
showError(
@@ -462,6 +502,7 @@ function init() {
decimals: 18,
balance: "0",
});
await saveState();
}
showAddressDetail();
});
@@ -471,9 +512,9 @@ function init() {
});
// -- Settings --
$("btn-save-rpc").addEventListener("click", () => {
$("btn-save-rpc").addEventListener("click", async () => {
state.rpcUrl = $("settings-rpc").value.trim();
// TODO: persist via background
await saveState();
});
$("btn-settings-back").addEventListener("click", () => {