Skip to Content
ReferenceSDKWorkspaces

Workspaces

Attach a Workspace (per-address dashboard) to a wallet, a mainnet contract, or a contract you’ve deployed and have an ABI for — from a script.

For bulk creation from a Hardhat/Foundry project’s compiled artifacts, use import-contracts instead.

stagenet.addWorkspace(input)

Create a Workspace. The server auto-dispatches based on what you pass — you never declare the Workspace “type” yourself.

const result = await stagenet.addWorkspace({ address: "0x28C6c06298d514Db089934071355E5743bf21d60", name: "Binance Hot Wallet", }); result.kind; // → "wallet" | "mainnet-contract" | "manual"

Input

FieldTypeDescription
namestringDisplay name shown in the dashboard. Required.
addressstring?The address to attach the Workspace to. Omit only for ABI-only manual Workspaces (have an ABI but no deployment yet).
abistring?JSON-encoded ABI string. When provided, creates a manual Workspace.
type'ERC20' | 'ERC721'?UI hint for mainnet-contract Workspaces. Ignored otherwise.

Dispatch rules

You provideWhat gets created
address only, no on-chain code at the addresswallet Workspace
address only, code matches mainnetmainnet-contract Workspace (ABI fetched from Etherscan on demand)
address + abimanual Workspace, with deployment linked to the address
abi only, no addressmanual Workspace, ABI-only (scaffold before deploy)

If you pass address for a contract that lives only on your Stagenet (not mainnet) and don’t include abi, the server returns an actionable error telling you to pass abi or run contract.dev import-contracts.

Result

The result is a discriminated union keyed by kind — switch on it to read per-flavor fields:

const result = await stagenet.addWorkspace({ address, name: "Vault" }); switch (result.kind) { case "wallet": console.log("wallet id:", result.wallet.id); break; case "mainnet-contract": console.log("contract id:", result.mainnetProjectContract.id); break; case "manual": console.log("contract id:", result.projectContract.id); console.log("deployment:", result.projectContractDeployment?.address); break; }

Full shape:

type AddWorkspaceResult = | { kind: "wallet"; wallet: { id: string; name: string | null; address: string; createdAt: string }; } | { kind: "mainnet-contract"; mainnetProjectContract: { id: string; name: string; address: string; type: string | null; createdAt: string; }; } | { kind: "manual"; projectContract: { id: string; name: string }; projectContractVersion: { id: string }; projectContractDeployment: { id: string; address: string } | null; };

Usage

Track a whale wallet

const result = await stagenet.addWorkspace({ address: "0x28C6c06298d514Db089934071355E5743bf21d60", name: "Binance Hot Wallet", }); // result.kind === "wallet"

The address has no on-chain code, so a wallet Workspace is created.

Attach to a real mainnet contract

const result = await stagenet.addWorkspace({ address: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", name: "USDC", type: "ERC20", }); // result.kind === "mainnet-contract"

The code at the address matches mainnet, so the ABI is fetched from Etherscan on demand. type toggles token-specific dashboard views.

Attach to a contract you deployed

const abi = JSON.stringify(VaultArtifact.abi); const result = await stagenet.addWorkspace({ address: "0xYourVault...", name: "MyVault", abi, }); // result.kind === "manual"

Scaffold a Workspace before deploy

const result = await stagenet.addWorkspace({ name: "FutureVault", abi: JSON.stringify(VaultArtifact.abi), }); // result.kind === "manual"; deployment is null until linked.

ABI-only Workspaces have no deployment until you re-call addWorkspace with the same name and the deployed address — useful for setting up dashboards in a deploy script before the contract lands on-chain.

CLI equivalent

contract.dev workspace add 0x28C6... --name "Binance Hot Wallet"

See CLI: workspace.

Last updated on