Node & Browser
Running the same API in both runtimes: the side-effect import "wative-core/node" plus filesystem storage in Node versus IndexedDB and the required Buffer polyfill in the browser.
wative-core runs in Node and in the browser with the same API. The domain objects — Workspace, Account, Wallet, Address — behave identically; what changes is where records are stored and a small amount of one-time setup. This page collects everything that differs so you can set up either runtime correctly.
What differs
| Node | Browser | |
|---|---|---|
| Extra import | import "wative-core/node" | none |
| Storage | encrypted files on disk | IndexedDB |
| Where it lives | Workspace.open({ path }), or the default location | IdbProvider.create(name) |
| Extra setup | none | Buffer polyfill |
Everything else — creating accounts, deriving wallets, signing, transactions — is written once and runs in both.
Node: the side-effect import
In Node you import the package for its side effect once, anywhere before you open a workspace:
import { Workspace } from "wative-core";
import "wative-core/node"; // registers the filesystem backends
const ws = await Workspace.open({ password: "your-workspace-password" });Importing wative-core/node registers the filesystem backends with the core, which is what lets Workspace.open() accept a path — or no argument at all — and write encrypted files to disk. Without that import, opening a workspace in Node throws, and the error tells you to add it.
wative-core/node also re-exports the Node-only classes HybridProvider, HybridProviderV3, and FileSink; for convenience these are re-exported from the package root in Node as well. See Node providers.
When you call Workspace.open({ password }) with no path, the location resolves through a 3-tier strategy: the WATIVE_WORKSPACE_PATH environment variable, then <cwd>/.wative2 if it exists, then <home>/.wative2. Pass an explicit path to short-circuit all three. See Opening a workspace.
Browser: storage and setup
The browser build stores records in IndexedDB in the current origin. There is no side-effect import — you build an IdbProvider and pass it to Workspace.open().
Add the Buffer polyfill
The Solana libraries read a global Buffer, which browsers do not provide. Install it:
pnpm add buffernpm i bufferThen, once, before importing wative-core:
import { Buffer } from "buffer";
globalThis.Buffer = Buffer;Open with an IdbProvider
import { Workspace, IdbProvider } from "wative-core";
const provider = await IdbProvider.create("my-dapp");
const ws = await Workspace.open({ provider, password: "your-workspace-password" });Browser storage is not permanent — a browser may clear IndexedDB when disk runs low. Creating a new workspace in non-persistent storage is refused with STORAGE_NOT_DURABLE. Call IdbProvider.create() from a user action (browsers grant persistence far more readily then), and give users a backup via exportContainer(). See IdbProvider.
Take the provider from the same entry point
Each entry point of the package is a separate bundle with its own class identities and module state. A provider built by one is not recognized by a Workspace from another, so import both from the same specifier:
// Right — one entry point.
import { Workspace, HybridProvider } from "wative-core";
const ws = await Workspace.open(new HybridProvider("~/wallets"), password);// Wrong — rejected with a PARAMETER_ERROR that names the fix.
import { Workspace } from "wative-core";
import { HybridProvider } from "wative-core/node";A bare import "wative-core/node" for its side effects is unaffected by this — the rule is only about handing a provider instance across entry points.
Content-Security-Policy and WebAssembly
Key derivation runs on a bundled WebAssembly build by default. In a browser with a Content-Security-Policy, grant 'wasm-unsafe-eval' in script-src, or derivation silently degrades to a pure-JS path that produces identical keys roughly 17x slower. The degradation is announced once on the console, and you can detect it programmatically:
import { argon2BackendInfo } from "wative-core";
argon2BackendInfo();
// -> { backend: "wasm" | "noble" | "unresolved", wasm, reason?, overrides }argon2BackendInfo() is a pure read that resolves nothing, so before the first unlock it honestly answers "unresolved".
Runtime support
Node.js 22.12+ is fully supported. Deno, Bun, and browser support is partial — some chain libraries ship as compiled dependencies that do not yet have universal builds, and a few lack pre-built binaries for Windows-ARM64 and Alpine-musl. Most installs on macOS, Linux x64, and Linux ARM64 will not notice.