Build React Apps on Sui with dApp Kit

Introducing a new SDK for developers to start building quickly and efficiently

Build React Apps on Sui with dApp Kit

Today Mysten Labs introduced dApp Kit, an all-in-one solution for developing React applications and decentralized applications (dApps) on Sui. The @mysten/dapp-kit is a brand-new SDK tailored for React and designed to streamline essential tasks such as connecting to wallets, signing transactions, and fetching data from RPC nodes. dApp Kit offers both themeable, pre built components like to simplify wallet interactions, as well as lower-level hooks and utilities to simplify creating your custom components.

dApp kit is a distillation of lessons learned from Mysten Labs, created with a goal of making it easier for everyone to start building dApps. In fact, Mysten Labs is starting to use dApp kit across all their own dApps; from Sui Explorer to Sui Wallet, every app we built uses dApp kit. We are just getting started, but we are excited to share the kit, and help get it into the hands of more builders!

For comprehensive documentation on dApp Kit, check out the full docs. In this blog post, we will guide you through setting up dApp Kit in your React project.

Installation

To get started with dApp Kit, first install it along with react-query:

npm install --save @mysten/dapp-kit @mysten/sui.js @tanstack/react-query

With the packages installed, you need to set up some providers in the application to ensure that dApp Kit functions smoothly:

import '@mysten/dapp-kit/dist/index.css';

import { SuiClientProvider, WalletProvider } from '@mysten/dapp-kit';
import { getFullnodeUrl } from '@mysten/sui.js/client';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';

const queryClient = new QueryClient();
const networks = {
	localnet: { url: getFullnodeUrl('localnet') },
	devnet: { url: getFullnodeUrl('devnet') },
	testnet: { url: getFullnodeUrl('testnet') },
	mainnet: { url: getFullnodeUrl('mainnet') },
};

ReactDOM.createRoot(document.getElementById('root')!).render(
	<QueryClientProvider client={queryClient}>
		<SuiClientProvider networks={networks} defaultNetwork="devnet">
			<WalletProvider>
				<App />
			</WalletProvider>
		</SuiClientProvider>
	</QueryClientProvider>,
);

In this code snippet, you:

  • Import the necessary dApp Kit CSS for rendering components correctly.
  • Set up a react-query provider to manage the state of requests made by dApp Kit.
  • Initialize the SuiClientProvider, which provides an instance of SuiClient and manages the connected network.
  • Configure the WalletProvider, responsible for managing wallet connections.

Now that the app is set up properly, you can dive into using dApp Kit's features.

Connecting a Wallet

To enable users to connect their Sui Wallet to the dApp, you can easily add a ConnectButton:

import { ConnectButton } from '@mysten/dapp-kit';

function App() {
	return (
		<div>
			<nav>
				<ConnectButton />
			</nav>
			<section>Hello, world</section>
		</div>
	);
}

This code will render a Button that opens a Modal and prompts users to connect their wallet. Once connected, users will see their connected walle and have the option to disconnect their wallet again.

Managing Wallet State

dApp Kit provides a variety of hooks for managing wallet state. For instance, the useCurrentWallet hook enables you to retrieve information about the user's connected account:

import { ConnectButton, useCurrentAccount } from '@mysten/dapp-kit';

function App() {
	const account = useCurrentAccount();
	return (
		<div>
			<nav>
				<ConnectButton />
			</nav>
			<section>{account ? 'No wallet connected' : `Your address is ${account.address}`}</section>
		</div>
	);
}

This allows you to display relevant information based on the user's wallet status.

Fetching Data

dApp Kit also facilitates data fetching for the currently connected user. The useSuiClientQuery hook can be used to call RPC methods. You can use getOwnedObjects to access and display a list of objects owned by the connected account:

import { ConnectButton, useCurrentAccount } from '@mysten/dapp-kit';

function App() {
	const account = useCurrentAccount();
	return (
		<div>
			<nav>
				<ConnectButton />
			</nav>
			<section>{account ? 'No wallet connected' : <OwnedObjects />}</section>
		</div>
	);
}

export function OwnedObjects() {
	const account = useCurrentAccount()!;
	const { data } = useSuiClientQuery('getOwnedObjects', { owner: account.address });

	return (
		<ul>
			{data.data.map((object) => (
				<li key={object.data?.objectId}>{object.data?.objectId}</li>
			))}
		</ul>
	);
}

You can read more about the hooks available for making RPC calls in the docs.

Transaction Building

Many dApps require the ability to create and sign transaction blocks. dApp Kit simplifies this process with the useSignAndExecuteTransactionBlock hook. Let's create a button that sends SUI to a predefined address:

import { signAndExecuteTransactionBlock } from '@mysten/dapp-kit';
import { TransactionBlock } from '@mysten/sui.js/transactions';

export function SendSui() {
	const { mutateAsync: signAndExecuteTransactionBlock } = useSignAndExecuteTransactionBlock();

	function sendMessage() {
		const txb = new TransactionBlock();

		const coin = txb.splitCoins(txb.gas, [10]);
		txb.transferObjects([coin], 'Ox...');

		signAndExecuteTransactionBlock({
			transactionBlock: txb,
		}).then(async (result) => {
			alert('Sui sent successfully');
		});
	}

	return <button onClick={() => sendMessage()}>Send me Sui!</button>;
}

When the button is pressed it will:

  • Create a new TransactionBlock
  • Adds a splitCoins transaction that splits off SUI from the gas coin into a new coin
  • Adds a new transferObject transaction that transfers the new coin to another address
  • Signs and executes the TransactionBlock using the connected wallet
  • Triggers an alert to let you know when the transaction has been executed

And much more

dApp Kit has many more features to help you quickly and easily build dApps. For more details and advanced features, explore the full documentation.

Interested in contributing to the Sui blog? Complete this form.