NetworksNetworks

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.ts
import { Workspace, Network } from "wative-core";

The Network class

Constructor

The primary form takes a single NetworkInit object:

new-network.ts
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

FieldTypeRequiredNotes
slugSlug (branded string)yesURL-safe identifier, 3–32 characters, unique within the workspace. A stored network whose slug exceeds 32 characters no longer loads.
namestringyesDisplay name, 3–64 characters.
chainIdChainId (branded number)yesEVM chain id, or the library's pinned id for an SVM cluster.
rpcUrlstringyesPrimary JSON-RPC endpoint (back-compat). See rpcUrl validation; "" means "no RPC configured". When endpoints is omitted it is the sole entry of the default pool.
endpointsreadonly string[]noOrdered default endpoint pool (failover order). Falls back to [rpcUrl] when omitted.
readEndpointsreadonly string[]noOptional read-only pool; falls back to endpoints, then [rpcUrl].
writeEndpointsreadonly string[]noOptional send pool; falls back to endpoints, then [rpcUrl].
routesNetworkRoutesnoOptional per-route endpoint pools (staked / jito / mev). See NetworkRoutes.
nativeCurrency{ name; symbol; decimals }yesname 1–32 chars, symbol 2–16 chars, decimals a non-negative integer.
multicallAddressstringnoMulticall3 contract (EVM address). Built-in EVM networks ship one; it is overridable and resets to defaultMulticallAddress.
colorstringnoHex color (e.g. #627eea), when provided.
vmVmTokenyes"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. The read-only network.defaultRpcUrl getter returns this network's canonical built-in RPC URL — see Resetting to the built-in RPC URL — and network.defaultMulticallAddress does the same for the Multicall3 contract (see Resetting to the built-in multicall). The read-only network.isBuiltin getter is true for a network wative-core ships as a built-in — the flag a UI reads to show it as non-deletable, with only its connectivity/presentation fields editable (its chain identity is fixed by the library). See Built-in Networks.

NetworkRoutes

routes supplies per-route endpoint pools for landing-optimized and private submission, alongside the ordinary endpoints / readEndpoints / writeEndpoints pools. Every key is optional and validated at construction.

RouteShapePurpose
staked{ endpoints: readonly string[] }A staked / landing-optimized RPC pool (ordinary JSON-RPC).
jito{ blockEngineUrl: string; tipAccount?: string }SVM Jito bundle route — its own block-engine URL and an optional tip account.
mev{ relayUrl: string }EVM private / MEV relay (e.g. Flashbots Protect / MEV-Share).

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.

lookup.ts
ws.networks.length;                     // 15 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 methods

bySlug and byChainId

Both return the matching Network, or null when nothing matches.

resolve.ts
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
MethodSignatureReturns
bySlugbySlug(slug: Slug)Network | null
byChainIdbyChainId(id: ChainId)Network | null

add / update / drop

MethodSignaturePurpose
addadd(network: Network) → Promise<Network>Register a new network. Persists.
updateupdate(network: Network) → Promise<Network>Replace the entry with the same slug. Persists.
dropdrop(network: Network) → Promise<void>Remove a user-added network. Persists.

Adding a slug that is already registered rejects with DUPLICATE_IDENTITY:

add.ts
await ws.networks.add(monad);
ws.networks.length;                          // 16
ws.networks.bySlug("monad-testnet").chainId; // 10143

await ws.networks.add(monad);
// rejects → WativeError { code: "DUPLICATE_IDENTITY" }

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:

override-rpc.ts
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; // 15 — replaced, not appended

Resetting to the built-in RPC URL

network.defaultRpcUrl is a read-only getter that returns the canonical RPC URL this network ships with — read straight from the frozen built-in registry, independent of any override the workspace copy carries. network.rpcUrl is the effective endpoint (your override, once you call update()); network.defaultRpcUrl is the value it resets back to.

reset-rpc.ts
const eth = ws.networks.bySlug("ethereum");
eth.rpcUrl;        // "https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY" (overridden)
eth.defaultRpcUrl; // the built-in default — unchanged by the override

// restore the shipped endpoint
await ws.networks.update(new Network({ ...eth, rpcUrl: eth.defaultRpcUrl }));

Resetting to the built-in multicall

The same model applies to the Multicall3 contract. Every built-in EVM network ships one; network.multicallAddress is the effective value and network.defaultMulticallAddress is the shipped default it resets back to. Override and reset it exactly like the RPC URL above.

reset-multicall.ts
const eth = ws.networks.bySlug("ethereum");
eth.multicallAddress;        // the effective multicall (your override, once set)
eth.defaultMulticallAddress; // the built-in default

// override, then restore the shipped contract
await ws.networks.update(new Network({ ...eth, multicallAddress: "0x1111111111111111111111111111111111111111" }));
await ws.networks.update(new Network({ ...eth, multicallAddress: eth.defaultMulticallAddress }));

The built-in guard

Networks you added can be dropped; the built-ins that ship with the workspace cannot:

drop.ts
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.

network.assets

A network obtained from a workspace exposes network.assets — a live list of that network's tokens with add, update, drop, move and byId. A standalone Network (a shared built-in constant, or one not added to a workspace) exposes the same property as a read-only template whose mutators reject with UNSUPPORTED_OP. The collection and its methods are documented on the Assets page.

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:

default-network.ts
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:

unknown.ts
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.

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.

RuleBehavior
Missing schemeRejected — prefix with https://, http://, wss://, or ws://.
Allowed schemeshttps:, http:, wss:, ws:. Any other scheme is rejected.
Link-local / metadata hostRejected.
Empty string ("")Accepted — treated as no RPC configured.

Reordering with move

move(slug: Slug, toIndex: number): Promise<void>

Changes the persisted order of the networks — the order workspace.networks returns. toIndex is the slug's final 0-based position; moving it to its current index is a no-op. The write is persisted and rolls back on failure.

reorder.ts
await ws.networks.move("base", 0); // make Base the first network

Error codes

CodeRaised when
DUPLICATE_IDENTITYadd() a slug already registered.
PARAMETER_ERRORAn invalid NetworkInit (bad rpcUrl, out-of-range field, reserved SVM chain id claimed as non-svm, a vm that is neither a built-in nor a registered dialect's token); or an out-of-range move() toIndex.
RECORD_NOT_FOUNDmove() a slug the workspace does not have.
UNSUPPORTED_OPdrop() or save() a built-in network; defaultRpcUrl or defaultMulticallAddress on a custom network.
UNSUPPORTED_NETWORKsetDefaultNetwork() given a network the workspace does not know.

Last updated on