Networks
The Network class and workspace.networks collection — resolving bySlug/byChainId, adding a custom Network, overriding a built-in RPC URL with update(), dropping user networks, and account.setDefaultNetwork().
A Network is a mostly-flat data object describing one chain: its slug, display name, chain id, RPC endpoint, native currency, and virtual machine ("evm" or "svm"). Every workspace opens with a set of built-in networks already loaded, and you can add your own, override a built-in's RPC URL, or drop the ones you added. Both the class and its collection live behind the main entry:
import { Workspace, Network } from "wative-core";The Network class
Constructor
The primary form takes a single NetworkInit object:
const monad = new Network({
slug: "monad-testnet",
name: "Monad Testnet",
chainId: 10143,
rpcUrl: "https://testnet-rpc.monad.xyz",
nativeCurrency: { name: "Monad", symbol: "MON", decimals: 18 },
vm: "evm",
});A positional overload also exists — new Network(name, chainId, rpcUrl, nativeCurrency?, color?) — which derives the slug from name and infers vm from the chain id. The object form is preferred because every field is explicit.
NetworkInit
| Field | Type | Required | Notes |
|---|---|---|---|
slug | Slug (branded string) | yes | URL-safe identifier, unique within the workspace. |
name | string | yes | Display name, 3–64 characters. |
chainId | ChainId (branded number) | yes | EVM chain id, or the library's pinned id for an SVM cluster. |
rpcUrl | string | yes | JSON-RPC endpoint. See rpcUrl validation; "" means "no RPC configured". |
nativeCurrency | { name; symbol; decimals } | yes | name 1–32 chars, symbol 2–16 chars, decimals a non-negative integer. |
multicallAddress | string | no | An EVM address, when provided. |
color | string | no | Hex color (e.g. #627eea), when provided. |
vm | VmToken | yes | "evm" or "svm". Casual casing and surrounding whitespace are normalized ("EVM", " svm " are accepted). |
The read-only network.symbol getter is a shortcut for network.nativeCurrency.symbol.
vm is typed as VmToken (ChainVM | (string & {})), leaving room for custom chain dialects to register their own tokens. The value "sui" is reserved and currently rejected with UNSUPPORTED_OP.
The workspace.networks collection
workspace.networks is a read-only array of Network (the NetworkCollection interface) with lookup and mutation helpers. Numeric and slug indexing both work, and a workspace-defined network overrides a built-in of the same slug.
ws.networks.length; // 14 at a fresh open
ws.networks[0]; // first Network in the array
ws.networks["bnbchain"]; // by slug (proxy indexing)
ws.networks.map((n) => n.slug); // ordinary array methodsbySlug and byChainId
Both return the matching Network, or null when nothing matches.
ws.networks.bySlug("ethereum").chainId; // 1
ws.networks.bySlug("arbitrum-sepolia").vm; // "evm"
ws.networks.byChainId(8453).slug; // "base"
ws.networks.bySlug("does-not-exist"); // null| Method | Signature | Returns |
|---|---|---|
bySlug | bySlug(slug: Slug) | Network | null |
byChainId | byChainId(id: ChainId) | Network | null |
add / update / drop
| Method | Signature | Purpose |
|---|---|---|
add | add(network: Network) → Promise<Network> | Register a new network. Persists. |
update | update(network: Network) → Promise<Network> | Replace the entry with the same slug. Persists. |
drop | drop(network: Network) → Promise<void> | Remove a user-added network. Persists. |
Adding a slug that is already registered rejects with PARAMETER_ERROR:
await ws.networks.add(monad);
ws.networks.length; // 15
ws.networks.bySlug("monad-testnet").chainId; // 10143
await ws.networks.add(monad);
// rejects → WativeError { code: "PARAMETER_ERROR" }update() replaces the existing entry in place — the common use is overriding a built-in's RPC URL with your own provider. Build a fresh Network by spreading the existing one and pass it to update(); the collection length is unchanged because the slug already existed:
const eth = ws.networks.bySlug("ethereum");
const customEth = new Network({
...eth,
rpcUrl: "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY",
});
await ws.networks.update(customEth);
ws.networks.bySlug("ethereum").rpcUrl;
// "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY"
ws.networks.length; // 14 — replaced, not appendedThe built-in guard
Networks you added can be dropped; the built-ins that ship with the workspace cannot:
await ws.networks.drop(custom);
ws.networks.bySlug("my-net"); // null
const eth = ws.networks.bySlug("ethereum");
await ws.networks.drop(eth);
// rejects → WativeError { code: "UNSUPPORTED_OP" }A built-in's RPC URL is still fully editable through update() — the guard is only on removing it.
A workspace-owned Network also has a convenience network.save() that upserts it into its owning workspace (add if new, update if the slug exists). Calling save() on a shared built-in constant throws UNSUPPORTED_OP.
account.setDefaultNetwork
Each account carries a default network. account.defaultNetwork reads the resolved slug (a Slug); account.setDefaultNetwork(value) sets it and persists, returning a Promise<void>. The argument is a NetworkLike — Network | ChainId | string — so a slug, a numeric chain id, a hex chain id string, or a Network instance all resolve to the same network:
const acc = await ws.accounts.create("Desk", "wsp-pwd", MNEMONIC);
await acc.setDefaultNetwork("base"); // slug
acc.defaultNetwork; // "base"
await acc.setDefaultNetwork(8453); // chain id → "base"
await acc.setDefaultNetwork("0xa"); // hex chain id → "optimism"
await acc.setDefaultNetwork(Network.Arbitrum); // Network instance
acc.defaultNetwork; // "arbitrum"The choice survives a lock and reopen. An unresolvable value rejects with UNSUPPORTED_NETWORK:
await acc.setDefaultNetwork("does-not-exist");
// rejects → WativeError { code: "UNSUPPORTED_NETWORK" }
await acc.setDefaultNetwork(99999999);
// rejects → WativeError { code: "UNSUPPORTED_NETWORK" }NetworkLike string resolution also honors a few common aliases before slug lookup, so "mainnet"/"eth" map to ethereum, "bsc"/"binance" to bnbchain, "op" to optimism, and "sol" to solana.
A synchronous setter, account.defaultNetwork = value, is also available; it resolves the value the same way but its write to disk is fire-and-forget. Prefer setDefaultNetwork() when you need to await persistence or surface a write error.
rpcUrl validation
rpcUrl is trimmed before it is stored. An empty string is a supported "no RPC configured" state; the RPC client raises its own coded error if you try to use it. A non-empty value must be a valid URL with an allowed scheme, and hosts that resolve to link-local or cloud-metadata addresses are refused. All failures throw a WativeError with code PARAMETER_ERROR.
| Rule | Behavior |
|---|---|
| Missing scheme | Rejected — prefix with https://, http://, wss://, or ws://. |
| Allowed schemes | https:, http:, wss:, ws:. Any other scheme is rejected. |
| Link-local / metadata host | Rejected. |
Empty string ("") | Accepted — treated as no RPC configured. |
Error codes
| Code | Raised when |
|---|---|
PARAMETER_ERROR | add() a slug already registered; an invalid NetworkInit (bad rpcUrl, out-of-range field, reserved SVM chain id claimed as non-svm). |
UNSUPPORTED_OP | drop() or save() a built-in network; a vm of "sui". |
UNSUPPORTED_NETWORK | setDefaultNetwork() given a network the workspace does not know. |