Getting Started with Dubhe
Dubhe is a full-stack framework for building on-chain applications on Sui. You declare your data schema in TypeScript, generate typed Move modules, and use the client SDK to interact with your contracts from any JavaScript/TypeScript environment.
The development loop
1. Define data → dubhe.config.ts
2. Generate → dubhe generate
3. Write logic → sources/systems/
4. Deploy → dubhe publish
5. Interact → @0xobelisk/sui-clientStep 1 — Set up your environment
Make sure you have the required tools installed.
Step 2 — Create a project
Scaffold a new project from an official template with a single command:
pnpm create dubheStep 3 — Define your data model
Edit dubhe.config.ts to declare what data your DApp stores on-chain:
import { defineConfig } from '@0xobelisk/sui-common';
export const dubheConfig = defineConfig({
name: 'mygame',
description: 'My on-chain game',
resources: {
// Per-user data
level: 'u32',
stats: { fields: { attack: 'u32', hp: 'u32' } },
// DApp-wide data
total_players: { global: true, fields: { count: 'u32' } }
},
errors: {
player_not_found: 'Player does not exist'
}
});Step 4 — Generate Move code
dubhe generateThis produces typed Move modules in src/<name>/sources/codegen/. Never edit these files manually — re-run generate whenever you change the config.
Step 5 — Write your business logic
Create system contracts in sources/systems/. Use the generated APIs to read and write storage:
module mygame::level_system;
use dubhe::dapp_service::{DappStorage, UserStorage};
use dubhe::dapp_system;
use mygame::dapp_key::DappKey;
use mygame::migrate;
use mygame::level;
public entry fun level_up(
dapp_storage: &DappStorage,
user_storage: &mut UserStorage,
ctx: &mut TxContext,
) {
dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
let lv = level::get(user_storage);
level::set(user_storage, lv + 1, ctx);
}→ Using Generated Code · Systems Guide
Step 6 — Test
Run all unit tests:
dubhe testStep 7 — Deploy
Start a local node and deploy:
dubhe node # start local Sui node
dubhe publish --network localnetDo not use
sui client publishdirectly.dubhe publishcallsgenesis::runafter publishing, which creates theDappStorageobject and runs yourdeploy_hook. It also recordspackageId,dappStorageId, anddappHubIdto.history/sui_localnet/latest.json.
After publishing, generate a typed deployment.ts for the client:
dubhe store-config --network localnet --output-ts-path ./src/deployment.tsThis writes PackageId, DappHubId, DappStorageId, and FrameworkPackageId as named TypeScript exports that your frontend can import directly.
Step 8 — Call from TypeScript
import { Dubhe, loadMetadata } from '@0xobelisk/sui-client';
import { Transaction } from '@mysten/sui/transactions';
import { Network, PackageId, DappHubId, DappStorageId, FrameworkPackageId } from './src/deployment';
const metadata = await loadMetadata(Network, PackageId);
const dubhe = new Dubhe({
networkType: Network,
packageId: PackageId,
metadata,
secretKey: process.env.PRIVATE_KEY,
frameworkPackageId: FrameworkPackageId, // dubhe framework package ID (localnet only)
dappStorageId: DappStorageId
});
const tx = new Transaction();
await dubhe.tx.level_system.level_up({
tx,
onSuccess: (result) => console.log('tx:', result.digest)
});AI coding assistant
If you use Cursor or another AI coding assistant, install the dubhe-dapp
skill to give it accurate context about Dubhe’s API, config options, and
deployment workflow:
npx skills add 0xobelisk/dubhe --skill dubhe-dappAfter installation, your assistant automatically loads the right Dubhe
reference docs when you ask about dubhe.config.ts, system functions, the
CLI, or the TypeScript client SDK.
What’s next?
| Topic | Description |
|---|---|
| Resources | Deep-dive into all resource patterns |
| Access Control | Guards: version, pause, admin |
| Contract Upgrading | How to safely upgrade your DApp |
| CLI Reference | All dubhe commands explained |
| Client SDK | Full SDK reference |
| Indexer | Index events for off-chain queries |