Accounts and wallet
Named identities, funding, and the dev wallet.
Declare the identities your app and tests sign with using account(name, opts?). The bare form
gives you a ready-to-use account: it creates an ephemeral key and funds it with the default SUI
amount on faucet-bearing local networks, so you can publish and transact straight away.
To bring your own key — a CI secret, or a fixed identity you want to reuse — use the signer
variant and pass any @mysten/sui Signer or Keypair. Load a secret from an env var or an inline
suiprivkey1... literal by constructing the keypair yourself:
import { account } from '@mysten-incubation/devstack';
import { Ed25519Keypair } from '@mysten/sui/keypairs/ed25519';
const alice = account('alice');
const ci = account('ci', {
kind: 'signer',
signer: Ed25519Keypair.fromSecretKey(process.env.ALICE_PRIVATE_KEY!),
});
const demo = account('demo', {
kind: 'signer',
signer: Ed25519Keypair.fromSecretKey('suiprivkey1...'),
});The kind field selects one of three account variants: ephemeral (the default — a fresh generated
key), signer (bring your own keypair, as above), and impersonate — fork-mode only —
account('whale', { kind: 'impersonate', address: '0x…' }), which acts as an existing on-chain
address by paying from a seeded reserve rather than signing.
To fund an account with specific coins and amounts, pass a funding list of { coin, amount }
entries:
import { account } from '@mysten-incubation/devstack';
const alice = account('alice', {
funding: [{ coin: 'sui', amount: 2_000_000_000n }],
});Add a wallet() member to make your accounts available in the app as a dev wallet — connect and
sign without standing up a real wallet. In dev, devstack injects the wallet onto the page and dApp
Kit auto-discovers it via wallet-standard, so it's ready to connect with no extra wiring. Use
wallet() to expose every account, or wallet({ accounts }) to scope it to a chosen set:
import {
defineDevstack,
account,
HOST_SERVICE_PORT_TOKEN,
hostService,
sui,
wallet,
} from '@mysten-incubation/devstack';
const DEV_PORT = 5173;
const localnet = sui();
const alice = account('alice');
const bob = account('bob');
const devWallet = wallet({
accounts: [alice, bob],
});
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: [devWallet] as const,
});
export default defineDevstack({ members: [localnet, app], stackName: 'main' });wallet({ accounts: 'all' }) expands to every account member in the final defineDevstack(...)
call. Either way, the dev wallet is injected and ready to connect in dev, and a production build
carries no dev wallet.
Under the hood
The wallet runs a small local server (bound to 0.0.0.0 by default) that the injected page talks
to. It keeps its pairing token and dApp Kit handles under the per-stack gitignored runtime output at
.devstack/stacks/<stack>/, and accepts the stack-scoped dev-server origin —
http://dev.<app>.localhost:5175 for the default stack, or
http://dev.<stack>.<app>.localhost:5175 for a named stack. Add allowedOrigins for nonstandard
browser origins.