Live Networks
Running the same stack shape against public networks.
Pick a Sui mode explicitly in the config. sui() is the local shorthand; public networks use
sui({ mode: 'live', network }).
import {
defineDevstack,
sui,
account,
HOST_SERVICE_PORT_TOKEN,
hostService,
knownPackage,
wallet,
} from '@mysten-incubation/devstack';
const DEV_PORT = 5173;
const alice = account('alice', {
kind: 'env',
key: 'ALICE_PRIVATE_KEY',
});
const registry = knownPackage('registry', {
packageId: '0x...',
});
const liveSui = sui({ mode: 'live', network: 'testnet' });
const devWallet = wallet({
accounts: [alice],
});
const app = hostService({
name: 'app',
script: `pnpm exec vite --host 127.0.0.1 --strictPort --port ${HOST_SERVICE_PORT_TOKEN}`,
port: DEV_PORT,
ready: { kind: 'http' },
after: [registry, devWallet] as const,
});
export default defineDevstack({
members: [liveSui, app],
stackName: 'main',
});The CLI can also select the surface network for mode-narrowed configs:
devstack up --network testnet
devstack up --network mainnet
devstack up --network testnet-forkFork mode runs a local sui-fork container against an upstream public network. It exposes the same
devstack Sui RPC route as other modes, but it does not expose a faucet or GraphQL endpoint. First
boot builds the bundled sui-fork image from a pinned Sui revision, so expect the cold path to take
longer than localnet.
import { defineDevstack, sui, account, localPackage } from '@mysten-incubation/devstack';
const publisherAddress = process.env.PUBLISHER_ADDRESS!;
const aliceAddress = process.env.ALICE_ADDRESS!;
const forkedTestnet = sui({
mode: 'fork',
upstream: 'testnet',
seed: { addresses: [publisherAddress, aliceAddress] },
});
const publisher = account('publisher', {
kind: 'impersonate',
address: publisherAddress,
});
const alice = account('alice', {
kind: 'impersonate',
address: aliceAddress,
});
const pkg = localPackage('demo', {
sourcePath: './move/demo',
publisher,
});
export default defineDevstack({
members: [forkedTestnet, pkg],
stackName: 'fork-demo',
});Use funded upstream addresses with fork mode. kind: 'impersonate' accounts submit empty-signature
transactions through the fork admin surface, which is useful for deterministic local replay, but no
private key exists and direct signing APIs intentionally fail.
Network names accepted by --network and DEVSTACK_NETWORK are localnet, testnet, mainnet,
devnet, testnet-fork, mainnet-fork, and devnet-fork; the same names are accepted with a
sui: prefix. The local alias maps to localnet.
Local-only services may refuse live or fork modes. Use the mode-specific factories when you want the type system to narrow available branches:
import { chainId, walrusFor, sealFor, deepbookFor } from '@mysten-incubation/devstack';
const live = { mode: 'live', chain: chainId('sui:testnet') } as const;
const fork = { mode: 'fork', chain: chainId('sui:testnet-fork') } as const;
const wal = walrusFor(live).known({
systemObjectId: '0x...',
stakingPoolId: '0x...',
nodes: [],
});
const forkWal = walrusFor(fork).known({
systemObjectId: '0x...',
stakingPoolId: '0x...',
nodes: [],
});
const keyServer = sealFor(live).testnet({
objectId: '0x...',
keyServerUrl: 'https://example.test/key',
});
const forkKeyServer = sealFor(fork).forkKnown({
upstream: 'testnet',
objectId: '0x...',
keyServerUrl: 'https://example.test/key',
});
const dex = deepbookFor(live).known({
packageId: '0x...',
registryId: '0x...',
});Live accounts should use env, keystore, inline, or signer as appropriate. Fork replay
accounts can use impersonate. The default ephemeral form is designed for local development, not
custody of real assets.