Mysten Incubation
Configure your stack

Coins and Funding

Coin declaration forms, managed coins, and how account funding works.

Declare the coins your accounts hold, then fund those accounts at boot so your app starts with balances in place. The coin namespace has three forms, one per provenance — a coin from a package you publish, a protocol builtin, or an already-deployed on-chain type — and funding follows from whether devstack can mint the coin: SUI from the faucet, managed package coins from their treasury cap.

devstack.config.ts
import { dirname, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import { account, coin, defineDevstack, localPackage, sui } from '@mysten-incubation/devstack';

const HERE = dirname(fileURLToPath(import.meta.url));

const localnet = sui();
const publisher = account('publisher');

const managed = localPackage('managed_coin', {
	sourcePath: resolve(HERE, 'move/managed_coin'),
	publisher,
});

const studio = coin.fromPackage(managed, 'MANAGED_COIN');

const alice = account('alice', {
	funding: [
		{ coin: 'sui', amount: 1_000_000_000n },
		{ coin: studio, amount: 1_000n },
	],
});

export default defineDevstack({ members: [localnet, managed, alice], stackName: 'main' });

Coin forms

  • coin.builtin('sui') — the protocol SUI type, 0x2::sui::SUI, with known decimals (9). Pure synchronous lookup; baked as a literal into codegen.
  • coin.fromPackage(member, witness) — a coin published by a localPackage(...) or knownPackage(...) member, looked up by (package, witness) after the package publishes. It adds a dependency edge on the package member, so publish and coin discovery complete before any funding tries to use the coin. Generated bindings carry the discovered CoinMetadata / coin_registry::Currency fields.
  • coin.known(fullCoinType) — an already-deployed on-chain type (0x…::module::WITNESS), resolved through a metadata read. Use it for live-network coins no local package publishes.

Managed coins

A managed coin is one devstack can both identify and mint for accounts. A coin is managed when:

  • it's declared with coin.fromPackage(localPackageMember, witness);
  • the publish output includes the coin metadata and a TreasuryCap for that witness;
  • the publisher still owns that cap (so it stays available as the funding signer).

When those hold, the coin gains a coinType:<fullCoinType> funding strategy that mints from the treasury cap. Account funding, DeepBook pool seeding, and the dashboard fund button all mint through that same strategy. You then fund an account with the coin directly:

const alice = account('alice', {
	funding: [{ coin: studio, amount: 1_000n }],
});

Account funding entries

Each entry in an account's funding array names a coin and an amount:

account('trader', {
	kind: 'ephemeral',
	funding: [
		{ coin: 'sui', amount: 1_000_000_000_000n }, // 'sui' shorthand → the faucet
		{ coin: usdc, amount: 5_000_000_000n }, // a managed coin → its treasury cap
		{ coin: dbtc, amount: 100_000_000n, via: deepbook }, // via: a strategy-provider edge
	],
});
  • { coin: 'sui', amount } is shorthand for SUI funding through the faucet — no coin.builtin('sui') needed.
  • { coin: <ref>, amount } funds any resolved coin ref through its coinType:<fullCoinType> strategy.
  • via adds a dependency edge on the member that provides the strategy (e.g. a DeepBook instance), so that provider resolves before funding runs. Use it when the coin's funding comes from a service rather than its own package publish. via is only valid on a coin-ref entry ({ coin: <ref> }); the { coin: 'sui' } shorthand always funds through the faucet and takes no via.

Amounts are in the coin's smallest unit (MIST for SUI).

Which coins can be funded

You can reference more coins than you can fund. A coin is fundable when something provides a funding strategy for it:

  • SUI is fundable when the active Sui network provides a faucet strategy. Explicit SUI funding throws when none exists, since default account funding depends on it.
  • Managed local-package coins are fundable from their treasury cap, as above.
  • Service coins like walCoin(localWalrus) are fundable when their service provides a matching coinType:<fullCoinType> strategy.
  • coin.known(fullCoinType) resolves metadata for an external coin so app code and bindings can reference it. To fund it, provide a strategy through the service that owns the mint, or pass via on the funding entry.

A missing non-SUI strategy is a no-op, so optional service funding stays ergonomic; a missing SUI strategy raises an error.

Funding runs per network: each strategy is keyed by coinType:<fullCoinType> (or faucet:request:<chainId> for SUI) and resolved against the current network, so a stack funds only on its own network. See Faucet and funding strategies for how strategies are provided and dispatched.

On this page