@mysten/sui v2.0 and a new dApp Kit are here! Check out the migration guide
Mysten Labs SDKs
MigrationsMigrate to 2.0

@mysten/dapp-kit

This guide helps you migrate from the original @mysten/dapp-kit (legacy) to the new @mysten/dapp-kit-react package.

The legacy @mysten/dapp-kit package will continue to work with the latest SDK, but it only supports JSON-RPC and will not receive further updates. We recommend migrating to @mysten/dapp-kit-react for new features and gRPC support.

Overview

The new dApp Kit SDK represents a complete rewrite with these key changes:

  • Framework agnostic: Split into @mysten/dapp-kit-core (framework-agnostic) and @mysten/dapp-kit-react (React bindings)
  • No React Query dependency: Direct promise-based API instead of mutation hooks
  • Web Components: UI components built with Lit Elements for cross-framework compatibility
  • Smaller bundle size: No React Query dependency, lighter state management with nanostores
  • Better SSR support: Compatible with SSR frameworks like Next.js
  • Cross-framework compatibility: Core functionality can be used in vanilla JS, Vue, React, and other frameworks

Step-by-Step Migration

1. Update Dependencies

Remove the old package and install the new ones:

npm uninstall @mysten/dapp-kit
npm i @mysten/dapp-kit-react @mysten/dapp-kit-core @mysten/sui

2. Create dApp Kit Instance

Create a new instance of the dApp Kit using the createDAppKit function and register the global type.

// dapp-kit.ts
import { createDAppKit } from '@mysten/dapp-kit-react';
import { SuiGrpcClient } from '@mysten/sui/grpc';

const GRPC_URLS = {
	testnet: 'https://fullnode.testnet.sui.io:443',
};

export const dAppKit = createDAppKit({
	networks: ['testnet'],
	createClient(network) {
		return new SuiGrpcClient({ network, baseUrl: GRPC_URLS[network] });
	},
});

// global type registration necessary for the hooks to work correctly
declare module '@mysten/dapp-kit-react' {
	interface Register {
		dAppKit: typeof dAppKit;
	}
}

3. Register Types

The declare module block in the previous step registers your dApp Kit instance's type globally. This enables all hooks like useDAppKit(), useCurrentNetwork(), and useCurrentClient() to automatically infer the correct types based on your configuration (e.g., your specific networks and client type).

declare module '@mysten/dapp-kit-react' {
	interface Register {
		dAppKit: typeof dAppKit;
	}
}

Without this registration, hooks return generic types and you lose type safety for things like network names. If you prefer not to use global type registration, you can pass the dAppKit instance explicitly to each hook instead:

const connection = useWalletConnection({ dAppKit });
const network = useCurrentNetwork({ dAppKit });

4. Replace Provider Setup

Replace the nested dApp Kit providers with a single unified provider. You can keep your existing QueryClientProvider for data fetching.

  // App.tsx
  import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
- import { SuiClientProvider, WalletProvider } from '@mysten/dapp-kit';
+ import { DAppKitProvider } from '@mysten/dapp-kit-react';
+ import { dAppKit } from './dapp-kit.ts';

  export function App() {
  	const queryClient = new QueryClient();
- 	const networkConfig = {
- 		mainnet: { url: 'https://mainnet.sui.io:443' },
- 		testnet: { url: 'https://testnet.sui.io:443' },
- 	};

  	return (
  		<QueryClientProvider client={queryClient}>
- 			<SuiClientProvider networks={networkConfig} defaultNetwork="mainnet">
- 				<WalletProvider>
- 					<App />
- 				</WalletProvider>
- 			</SuiClientProvider>
+ 			<DAppKitProvider dAppKit={dAppKit}>
+ 				<App />
+ 			</DAppKitProvider>
  		</QueryClientProvider>
  	);
  }

5. Configuration Option Changes

The createDAppKit function has different configuration options than the old WalletProvider:

Old (WalletProvider)New (createDAppKit)Notes
-networks (required)List of network identifiers your app supports
-createClientFunction to create a client for each network
-defaultNetworkNetwork to use by default (defaults to first in networks)
autoConnect (false)autoConnect (true)Default changed from false to true
enableUnsafeBurnerenableBurnerWalletRenamed
slushWalletslushWalletConfigRenamed
storagestorageUnchanged
storageKeystorageKeyUnchanged
preferredWallets-Removed
walletFilter-Removed (wallets filtered by network compatibility)
theme-Removed (UI components are now web components with built-in styling)
-walletInitializersNew option for registering custom wallets

6. Update Hook Usage

The new dApp Kit has a dramatically simplified hook API. Most hooks from the original version have been replaced with direct action calls through useDAppKit().

Available hooks in the new version:

  • useDAppKit() - Access the dAppKit instance for calling actions
  • useCurrentClient() - Get the blockchain client (renamed from useSuiClient)
  • useCurrentAccount() - Get the current connected account
  • useCurrentWallet() - Get the current connected wallet
  • useWallets() - Get the list of available wallets
  • useWalletConnection() - Get the current wallet connection status
  • useCurrentNetwork() - Get the current network

Removed hooks:

All wallet action hooks have been replaced with direct action calls via useDAppKit():

  • useConnectWallet -> Use dAppKit.connectWallet()
  • useDisconnectWallet -> Use dAppKit.disconnectWallet()
  • useSignTransaction -> Use dAppKit.signTransaction()
  • useSignAndExecuteTransaction -> Use dAppKit.signAndExecuteTransaction()
  • useSignPersonalMessage -> Use dAppKit.signPersonalMessage()
  • useSwitchAccount -> Use dAppKit.switchAccount()

All data fetching hooks have been removed (giving you flexibility to use your preferred solution):

  • useSuiClientQuery -> Use useCurrentClient() with your data fetching solution
  • useSuiClientMutation -> Use useCurrentClient() with your data fetching solution
  • useSuiClientInfiniteQuery -> Use useCurrentClient() with your data fetching solution
  • useSuiClientQueries -> Use useCurrentClient() with your data fetching solution
  • useResolveSuiNSNames -> Use useCurrentClient() directly

Other removed hooks:

  • useAutoConnectWallet -> Auto-connect is enabled by default
  • useAccounts -> Use useWalletConnection() to access connection.wallet.accounts
  • useWalletStore -> Use specific hooks like useWalletConnection() instead

7. Replace Mutation Patterns

The built-in mutation hooks have been removed. Use TanStack Query's useMutation with useDAppKit() to get similar functionality.

Chain parameter replaced with network:

In the old dapp-kit, you could optionally pass a chain parameter (e.g., sui:mainnet) to methods like signTransaction and signAndExecuteTransaction. In the new dapp-kit, use the network parameter instead - the chain is automatically derived from the network.

- const { mutateAsync: signAndExecute } = useSignAndExecuteTransaction();
- await signAndExecute({ transaction, chain: 'sui:mainnet' });
+ const dAppKit = useDAppKit();
+ await dAppKit.signAndExecuteTransaction({ transaction, network: 'mainnet' });

Mutation example:

- import { useSignAndExecuteTransaction } from '@mysten/dapp-kit';
+ import { useMutation } from '@tanstack/react-query';
+ import { useDAppKit } from '@mysten/dapp-kit-react';
  import type { Transaction } from '@mysten/sui/transactions';

  export function ExampleComponent({ transaction }: { transaction: Transaction }) {
- 	const { mutateAsync: signAndExecute } = useSignAndExecuteTransaction();
+ 	const dAppKit = useDAppKit();
+
+ 	const { mutateAsync: signAndExecute } = useMutation({
+ 		mutationFn: (tx: Transaction) => dAppKit.signAndExecuteTransaction({ transaction: tx }),
+ 	});

  	const handleClick = async () => {
- 		await signAndExecute(
- 			{ transaction },
- 			{
- 				onSuccess: (result: any) => console.log(result),
- 				onError: (error: any) => console.error(error),
- 			},
- 		);
+ 		await signAndExecute(transaction, {
+ 			onSuccess: (result) => console.log(result),
+ 			onError: (error) => console.error(error),
+ 		});
  	};

  	return <button onClick={handleClick}>Sign and Execute</button>;
  }

Alternative: Direct promise-based calls

If you don't need React Query's state management, you can call dAppKit methods directly:

import { useDAppKit } from '@mysten/dapp-kit-react';
import type { Transaction } from '@mysten/sui/transactions';

export function ExampleComponent({ transaction }: { transaction: Transaction }) {
	const dAppKit = useDAppKit();

	const handleClick = async () => {
		try {
			const result = await dAppKit.signAndExecuteTransaction({ transaction });
			console.log(result);
		} catch (error) {
			console.error(error);
		}
	};

	return <button onClick={handleClick}>Sign and Execute</button>;
}

8. Replace Data Fetching Patterns

The built-in data fetching hooks have been removed. Use TanStack Query's useQuery with useCurrentClient() to get similar functionality:

- import { useSuiClientQuery } from '@mysten/dapp-kit';
+ import { useQuery } from '@tanstack/react-query';
+ import { useCurrentClient } from '@mysten/dapp-kit-react';

  export function ExampleComponent({ objectId }: { objectId: string }) {
+ 	const client = useCurrentClient();
+
- 	const { data, isLoading, error } = useSuiClientQuery('getObject', {
- 		id: objectId,
- 	});
+ 	const { data, isLoading, error } = useQuery({
+ 		queryKey: ['object', objectId],
+ 		queryFn: () => client.core.getObject({ objectId }),
+ 	});
  	// ...
  }

Alternative: Direct data fetching

If you don't need React Query's caching and state management, you can fetch data directly:

import { useCurrentClient } from '@mysten/dapp-kit-react';
import { useState, useEffect } from 'react';

export function ExampleComponent({ objectId }: { objectId: string }) {
	const client = useCurrentClient();
	const [data, setData] = useState(null);
	const [isLoading, setIsLoading] = useState(true);
	const [error, setError] = useState<string | null>(null);

	useEffect(() => {
		client.core
			.getObject({ objectId })
			.then((result) => setData(result.object ?? null))
			.catch((err) => setError(err.message))
			.finally(() => setIsLoading(false));
	}, [client, objectId]);
	// ...
}

9. Update The Remaining Code

The following hooks from the original dApp Kit are not available anymore:

  • useSuiClientQuery → Use useQuery from @tanstack/react-query
  • useSuiClientMutation → Use useMutation from @tanstack/react-query
  • useSuiClientInfiniteQuery → Use useInfiniteQuery from @tanstack/react-query
  • useResolveSuiNSNames → Use useCurrentClient() with the suins extension

The reportTransactionEffects feature is planned for deprecation in the Wallet Standard and so the dApp Kit provides no replacement.

The following have been removed:

  • useReportTransactionEffects hook
  • reportTransactionEffects callback from useSignTransaction
  • Automatic transaction effects reporting from useSignAndExecuteTransaction

CSS and Theming Changes

The new dApp Kit no longer bundles a CSS file. If you were importing the old CSS file, remove the import:

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

The new dApp Kit uses web components with built-in styling that can be customized using CSS custom properties. See the Theming documentation for details on customizing the appearance of dApp Kit components.

Quick theme setup:

:root {
	--primary: #4f46e5;
	--primary-foreground: #ffffff;
	--background: #ffffff;
	--foreground: #0f172a;
	--border: #e2e8f0;
	--radius: 0.5rem;
}

Removing TanStack Query

If you were only using @tanstack/react-query for dApp Kit and don't need it for other parts of your application, you can now remove it:

npm uninstall @tanstack/react-query

On this page