AssetsAssets

Assets

The Asset class — listing a network's tokens, the live network.assets collection, editing and persisting tokens with asset.save() and workspace.updateAsset, adding tokens with addAsset, and the AssetInitObject, AssetUpdate, AssetAddInit, AssetBalance, AssetCollection and NetworkAssetCollection types.

An Asset is token metadata bound to a Network: its id, symbol, name, decimals, and contract address. Every workspace is seeded with a curated set of built-in tokens and lets you import your own. This page covers constructing an Asset, listing a network's tokens, the live network.assets collection, adding, editing, persisting, removing and reordering tokens, and the related types.

The Asset class

Asset is a value export of wative-core. Construct one either from an init object or from positional arguments.

new-asset.ts
import { Asset, Network } from "wative-core";

// Object form (preferred).
const pepe = new Asset({
  id: 200,
  symbol: "PEPE",
  name: "Pepe",
  decimals: 18,
  contractAddress: "0x6982508145454Ce325dDbE47a25d4ec3d2311933",
  network: Network.Ethereum,
});

// Positional form: (id, symbol, name, decimals, network, contractAddress?)
const same = new Asset(200, "PEPE", "Pepe", 18, Network.Ethereum, "0x6982508145454Ce325dDbE47a25d4ec3d2311933");

AssetInitObject

The object accepted by the constructor.

FieldTypeRequiredNotes
idAssetIdyesA non-negative integer. AssetId is a branded number.
symbolstringyes1–32 characters.
namestringyes1–128 characters.
decimalsnumberyesToken decimals.
networkNetworkyesMust be a Network instance.
contractAddressstring | nullnonull for a native gas coin. Defaults to null.
displayDecimalsnumbernoDefaults to decimals; must be <= decimals.
displayStatusbooleannoDefaults to true.

Instance properties

PropertyTypeNotes
idAssetIdreadonly
contractAddressstring | nullreadonly; canonicalized on construction (EIP-55 for EVM). null for a native coin.
nativebooleanreadonly; derived. true when the address is null or the network's native placeholder.
symbolstring
namestring
decimalsnumber
displayDecimalsnumberDefaults to decimals.
displayStatusbooleanDefaults to true.
networkNetworkreadonly
isBuiltinbooleanreadonly; derived. true for a built-in token — it cannot be dropped and only displayStatus / displayDecimals are editable.

Identity (id, contractAddress, native, network) is fixed for the life of the token; the remaining fields are editable subject to the token's tier — a built-in token (asset.isBuiltin === true) allows only its display fields — see Which fields are editable.

Instance methods

MethodReturnsNotes
save()Promise<Asset>Persists edits to this token's editable fields and returns the refreshed asset. Rejects UNSUPPORTED_OP on an Asset not obtained from a workspace. See Editing a token.

Listing a network's tokens — workspace.assets(network)

assets(network: NetworkLike): Promise<readonly Asset[]>

network is a NetworkLike: either a Network instance or a network slug string (e.g. "sepolia", "arbitrum-sepolia"). The result is the built-in tokens for that network plus any you have imported.

list-assets.ts
import { Workspace, Network } from "wative-core";

const ws = await Workspace.open({ path: "./wallet", password: "wsp-pwd" });

// By Network instance…
const eth = await ws.assets(Network.Ethereum);
eth.map((a) => a.symbol); // ["ETH", "USDC", "USDT", "WETH"]

// …or by network slug.
const sepolia = await ws.assets("sepolia"); // length 1 — [ETH]

const arb = await ws.assets("arbitrum-sepolia");
const usdc = arb.find((a) => a.symbol === "USDC");
usdc?.decimals;         // 6
usdc?.native;           // false
usdc?.contractAddress;  // "0x75faf114eafb1BDbe2F0316DF893fd58CE46AA4d"

The live token list — network.assets

On a network obtained from a workspace — ws.networks.bySlug("ethereum"), or any entry of ws.networks — network.assets is a live NetworkAssetCollection: a read-only array of that network's tokens with a byId lookup and four mutators that add, edit, remove and reorder tokens and persist the change. This is the primary way to manage a network's tokens.

interface NetworkAssetCollection extends AssetCollection {
  add(init: Omit<AssetAddInit, "network">): Promise<Asset>;
  update(id: AssetId, patch: AssetUpdate): Promise<Asset>;
  drop(id: AssetId): Promise<void>;
  move(id: AssetId, toIndex: number): Promise<void>;
}
network-assets.ts
const eth = ws.networks.bySlug("ethereum");

// Add a token — the library allocates its id.
const pepe = await eth.assets.add({
  symbol: "PEPE",
  name: "Pepe",
  decimals: 18,
  contractAddress: "0x6982508145454Ce325dDbE47a25d4ec3d2311933",
});

eth.assets.byId(pepe.id)?.symbol;     // "PEPE"
await eth.assets.update(pepe.id, { displayStatus: false });
await eth.assets.move(pepe.id, 0);    // reorder within the network
await eth.assets.drop(pepe.id);

// It is still an array.
eth.assets.length;
eth.assets.map((a) => a.symbol);

update and drop are scoped to that network — an id belonging to a different network rejects with RECORD_NOT_FOUND.

Adding a custom token — addAsset

addAsset(init: AssetAddInit): Promise<Asset>

Imports a user token from its details; the library allocates the token's id. The write is persisted immediately and the in-memory list rolls back if persistence fails; the imported Asset is returned. network.assets.add(init) is the same call with the network taken from the collection.

add-asset.ts
const pepe = await ws.addAsset({
  network: Network.Ethereum,
  symbol: "PEPE",
  name: "Pepe",
  decimals: 18,
  contractAddress: "0x6982508145454Ce325dDbE47a25d4ec3d2311933",
});

pepe.id; // a library-allocated id (user ids start at 1000)

const eth = await ws.assets(Network.Ethereum);
eth.length; // 5 — the four built-ins plus PEPE

AssetAddInit

The details accepted by addAsset. The caller never supplies an id — the library allocates it.

FieldTypeRequiredNotes
networkNetworkLikeyesThe network to add the token to. Omitted when calling network.assets.add.
symbolstringyes1–32 characters.
namestringyes1–128 characters.
decimalsnumberyesToken decimals.
contractAddressstring | nullnonull for a native coin. Defaults to null.
displayDecimalsnumbernoDefaults to decimals; must be <= decimals.
displayStatusbooleannoDefaults to true.

addAsset throws a WativeError in these cases:

codeWhen
PARAMETER_ERRORThe argument is not an Asset or an asset-init object.
DUPLICATE_IDENTITYThe (network, contractAddress) pair is already present (including trying to claim the network's native slot).
UNSUPPORTED_NETWORKThe network is not registered with this workspace.
WORKSPACE_LOCKEDThe workspace is locked — addAsset requires it unlocked.

Address collisions are rejected

A token's (network, contractAddress) must be unique within the workspace, and the built-in tokens already occupy their addresses — re-using one rejects with DUPLICATE_IDENTITY. Because the library allocates ids, a caller can no longer collide on an id.

collisions.ts
// This address is already the built-in USDC.
await ws.addAsset({
  network: Network.Ethereum,
  symbol: "USDC2",
  name: "Other USDC",
  decimals: 6,
  contractAddress: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
}); // rejects: WativeError { code: "DUPLICATE_IDENTITY" }

Editing a token — updateAsset and asset.save()

updateAsset(id: AssetId, patch: AssetUpdate): Promise<Asset>

Edit a token either by id through the workspace, or by mutating an Asset you already hold and calling save(). Both persist the change and return the refreshed Asset.

edit-asset.ts
// By id, through the workspace (or network.assets.update(id, patch)).
await ws.updateAsset(pepe.id, { displayStatus: false, name: "Pepe Token" });

// Or edit a held Asset and save it.
const eth = await ws.assets(Network.Ethereum);
const token = eth.find((a) => a.id === pepe.id);
token.displayStatus = true;
await token.save();

save() rejects with UNSUPPORTED_OP on an Asset that did not come from the workspace (one you constructed yourself).

Which fields are editable

A token's identity — id, contractAddress, native, network — never changes. The rest depends on the token:

TokenEditable fields
User-addedsymbol, name, decimals, displayDecimals, displayStatus
Built-indisplayStatus, displayDecimals only

A write to a field the token does not allow — a built-in token's symbol, say — is refused with PARAMETER_ERROR; it is never silently dropped. An unknown id is RECORD_NOT_FOUND.

AssetUpdate

The patch accepted by updateAsset (and by network.assets.update and asset.save()). Every field is optional; identity fields are not accepted.

FieldTypeNotes
symbolstringUser tokens only.
namestringUser tokens only.
decimalsnumberUser tokens only.
displayDecimalsnumberMust be <= decimals.
displayStatusboolean

Dropping a token — dropAsset

dropAsset(id: AssetId): Promise<void>

Removes a user-imported token by id. Like addAsset, the write is persisted and rolls back on failure.

drop-asset.ts
await ws.addAsset(myToken); // id 300
await ws.dropAsset(300);

const eth = await ws.assets(Network.Ethereum);
eth.some((a) => a.id === 300); // false
codeWhen
UNSUPPORTED_OPThe id belongs to a built-in token — those are protected.
RECORD_NOT_FOUNDNo user asset with that id exists.
WORKSPACE_LOCKEDThe workspace is locked — dropAsset requires it unlocked.
await ws.dropAsset(1); // rejects: WativeError { code: "UNSUPPORTED_OP" }

Reordering tokens — moveAsset

moveAsset(network: NetworkLike, id: AssetId, toIndex: number): Promise<void>

Changes the persisted order of one network's tokens — the order assets(network) returns. toIndex is the token's final 0-based position among that network's assets; moving it to its current index is a no-op. The write is persisted and rolls back on failure, and other networks' order is untouched.

move-asset.ts
const eth = await ws.assets(Network.Ethereum);
await ws.moveAsset(Network.Ethereum, eth.at(-1).id, 0); // last → first
codeWhen
PARAMETER_ERRORtoIndex is out of range (negative, non-integer, or past the last asset).
RECORD_NOT_FOUNDNo asset with that id exists on the given network.
WORKSPACE_LOCKEDThe workspace is locked — moveAsset requires it unlocked.

Finding an asset

The workspace's general filter helper resolves a single Asset by symbol or contract address (returning null when nothing matches):

find-asset.ts
const bySymbol = ws.filter("USDC", "Asset");
bySymbol?.symbol; // "USDC"

const byAddr = ws.filter("0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "Asset");
byAddr?.symbol; // "USDC"

AssetBalance

A read of an on-chain balance for one asset. Balances live on an address, not on the Asset itself.

FieldTypeDescription
assetIdAssetIdWhich asset the balance is for.
rawbigintThe balance in base units (unscaled by decimals).
decimalsnumberThe asset's decimals, for formatting raw.
displayStatusbooleanWhether the asset is shown in balance listings.
fetchedAtnumberWhen the balance was read.
readError?stringOptional. Present only when this asset's balance could not be read (a delisted/not-a-token contract, a malformed node response, or a transport failure that outlasted failover). When set, raw is 0n and is not a real balance; the other assets' balances are still returned.

All fields are readonly; readError is optional and appears only on a failed read.

AssetCollection

interface AssetCollection extends ReadonlyArray<Asset> {
  byId(id: AssetId): Asset | null;
}

A read-only array of Asset with an added byId lookup. It is the type of an address's .assets property and the base of NetworkAssetCollection.

NetworkAssetCollection

interface NetworkAssetCollection extends AssetCollection {
  add(init: Omit<AssetAddInit, "network">): Promise<Asset>;
  update(id: AssetId, patch: AssetUpdate): Promise<Asset>;
  drop(id: AssetId): Promise<void>;
  move(id: AssetId, toIndex: number): Promise<void>;
}

The type of network.assets: an AssetCollection plus the four mutators. On a workspace-attached network they add, edit, remove and reorder that network's tokens; on a standalone Network they reject with UNSUPPORTED_OP.

See also

Last updated on