Sui dApp Development Guide
This comprehensive guide covers building modern decentralized applications (dApps) on the Sui blockchain using the latest tools and best practices for 2025.
Prerequisites
- Node.js 18+ for running the development environment
- Basic TypeScript/JavaScript knowledge for frontend development
- Understanding of React for UI components (optional but recommended)
- Sui wallet installed (Sui Wallet, Suiet, or other Sui-compatible wallets)
Core Technologies
Essential Packages
# Core Sui SDK (modular imports)
npm install @mysten/sui
# dApp Kit for React applications
npm install @mysten/dapp-kit
# Additional utilities
npm install @mysten/dapp-kit @tanstack/react-query
Package Overview
- @mysten/sui: Core SDK for blockchain interactions
- @mysten/dapp-kit: React hooks and components for wallet integration
- @tanstack/react-query: State management for async data (recommended)
Basic Setup
1. Initialize Sui Client
import { SuiClient, getFullnodeUrl } from '@mysten/sui/client';
// Initialize client for different networks
const client = new SuiClient({
url: getFullnodeUrl('mainnet') // 'testnet', 'devnet', 'localnet'
});
// Using BlockEden.xyz endpoint
const blockEdenClient = new SuiClient({
url: 'https://api.blockeden.xyz/sui/<access_key>'
});
2. React dApp Setup with dApp Kit
// App.tsx
import { SuiClientProvider, WalletProvider } from '@mysten/dapp-kit';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { getFullnodeUrl } from '@mysten/sui/client';
const queryClient = new QueryClient();
const networks = {
mainnet: { url: getFullnodeUrl('mainnet') },
testnet: { url: getFullnodeUrl('testnet') },
};
function App() {
return (
<QueryClientProvider client={queryClient}>
<SuiClientProvider networks={networks} defaultNetwork="testnet">
<WalletProvider>
<MyDApp />
</WalletProvider>
</SuiClientProvider>
</QueryClientProvider>
);
}
3. Wallet Connection Component
// WalletConnection.tsx
import { ConnectButton, useCurrentAccount } from '@mysten/dapp-kit';
export function WalletConnection() {
const currentAccount = useCurrentAccount();
return (
<div className="wallet-section">
<ConnectButton />
{currentAccount && (
<div>
<p>Connected: {currentAccount.address}</p>
</div>
)}
</div>
);
}
Working with Transactions
Building and Executing Transactions
import { Transaction } from '@mysten/sui/transactions';
import { useSignAndExecuteTransaction, useSuiClient } from '@mysten/dapp-kit';
export function TransferSui() {
const client = useSuiClient();
const { mutate: signAndExecute } = useSignAndExecuteTransaction();
const transferSui = async (recipient: string, amount: number) => {
const tx = new Transaction();
// Convert SUI to MIST (1 SUI = 1,000,000,000 MIST)
const amountMIST = amount * 1_000_000_000;
// Split coins and transfer
const [coin] = tx.splitCoins(tx.gas, [amountMIST]);
tx.transferObjects([coin], recipient);
// Execute transaction
signAndExecute(
{ transaction: tx },
{
onSuccess: (result) => {
console.log('Transfer successful:', result.digest);
},
onError: (error) => {
console.error('Transfer failed:', error);
},
}
);
};
return (
<button onClick={() => transferSui('0x...', 1)}>
Send 1 SUI
</button>
);
}
Move Call Transactions
import { Transaction } from '@mysten/sui/transactions';
export function MoveCallExample() {
const { mutate: signAndExecute } = useSignAndExecuteTransaction();
const callMoveFunction = async () => {
const tx = new Transaction();
// Call a Move function
tx.moveCall({
target: '0x2::coin::split',
arguments: [
tx.object('0x...'), // coin object
tx.pure.u64(1000000000), // amount in MIST
],
});
signAndExecute({ transaction: tx });
};
return <button onClick={callMoveFunction}>Call Move Function</button>;
}