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
| Field | Type | Description |
|---|---|---|
name | string | Display name shown in the dashboard. Required. |
address | string? | The address to attach the Workspace to. Omit only for ABI-only manual Workspaces (have an ABI but no deployment yet). |
abi | string? | JSON-encoded ABI string. When provided, creates a manual Workspace. |
type | 'ERC20' | 'ERC721'? | UI hint for mainnet-contract Workspaces. Ignored otherwise. |
Dispatch rules
| You provide | What gets created |
|---|---|
address only, no on-chain code at the address | wallet Workspace |
address only, code matches mainnet | mainnet-contract Workspace (ABI fetched from Etherscan on demand) |
address + abi | manual Workspace, with deployment linked to the address |
abi only, no address | manual 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.