Getting StartedBrowser Extensions

Browser Extensions

The recommended setup for a browser extension or dapp — IdbProviderV3 for storage, session-key resume as the primary unlock, deriveWallets(N) with chunked progress, and argon2BackendInfo() to detect the slow CSP fallback.

wative-core runs in the browser with the same API as Node. Beyond the one-time setup on Node & Browser (the Buffer polyfill and storage durability), four opt-in choices make a wallet extension fast and resilient. The library's defaults stay backward-compatible, so set these four deliberately.

ConcernReach forWhy
StorageIdbProviderV3one key derivation per container — unlock stays fast at any account size
Unlocksession-key resume, password fallbackreopen an evicted background page with no password and no key stretching
Bulk derivederiveWallets(N) with { chunkSize, onProgress }one write, and a loop that yields so the tab never freezes
Resilienceargon2BackendInfo() on startupdetect a CSP that forces the slow fallback and warn the user

1 — Storage: IdbProviderV3

storage.ts
import { Workspace, IdbProviderV3 } from "wative-core";

const provider = await IdbProviderV3.create("my-wallet"); // opt-in
const ws = await Workspace.open({ provider, password });

IdbProviderV3 derives one container key rather than one per stored secret, so unlocking a large account stays fast instead of slowing down as wallets are added. It is also the only provider that can hand out a session key. A workspace it writes cannot be opened by older library versions, so choose it before the first write.

2 — Unlock: session key first, password as fallback

An extension's background page is evicted often, and re-prompting for the password each time is the main friction. A v3 workspace hands out a 32-byte session key that reopens it with no password:

resume.ts
// On the first (password) unlock, in the foreground:
const key = ws.exportSessionKey();                 // 32 bytes
await chrome.storage.session.set({ wk: Array.from(key) }); // memory-only; cleared when the browser quits

// Later, when the background page wakes with no password:
const { wk } = await chrome.storage.session.get("wk");
const ws2 = await Workspace.openWithSessionKey(provider, Uint8Array.from(wk));
// or resume a locked handle you still hold: await ws.unlockWithSessionKey(key);

See Session keys for the full contract.

3 — Bulk derivation without freezing the tab

Add wallets in one call, and pass { chunkSize, onProgress } so a large derivation yields to the browser between chunks and can drive a progress bar:

bulk-derive.ts
await account.deriveWallets(400, {
  chunkSize: 20,                                 // yield to the UI every 20 wallets
  onProgress: (done, total) => setBar(done / total),
});

Without options, deriveWallets(N) runs as one uninterrupted block — fine for a small count or off the main thread. With options it derives in chunks that yield a macrotask between them, so the main thread paints. Either way the whole batch writes to storage exactly once.

See Wallets.

4 — Resilience: detect the key-derivation backend

Argon2 runs on a bundled WebAssembly build. A Content-Security-Policy without 'wasm-unsafe-eval' blocks WebAssembly, and the library falls back to a pure-JS implementation that is roughly 17× slower — correct, but an unlock that was a fraction of a second becomes several. Detect it on startup and tell the user:

slow-mode.ts
import { argon2BackendInfo } from "wative-core";

// After the first unlock (it resolves lazily; before that it reads "unresolved"):
const info = argon2BackendInfo();
if (!info.wasm) {
  showSlowModeNotice(); // suggest granting 'wasm-unsafe-eval' in the extension's CSP
}

The library also logs the fallback once to the console. See Key derivation.

Last updated on