# @mysten/dapp-kit

> Migrate @mysten/dapp-kit to the new dapp-kit-react package in 2.0.

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

> **Note:** 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

### Step 1: Update dependencies

Remove the old package and install the new ones:

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

### Step 2: Create dApp Kit instance

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

```tsx
// dapp-kit.ts

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

	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;
	}
}
```

### Step 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 (for example, your specific
networks and client type).

```tsx
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:

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

### Step 4: Replace provider setup

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

```diff
  // 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>
  	);
  }
```

### Step 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                        |
| -                      | `createClient`        | Function to create a client for each network                         |
| -                      | `defaultNetwork`      | Network to use by default (defaults to first in `networks`)          |
| `autoConnect` (false)  | `autoConnect` (true)  | Default changed from `false` to `true`                               |
| `enableUnsafeBurner`   | `enableBurnerWallet`  | Renamed                                                              |
| `slushWallet`          | `slushWalletConfig`   | Renamed                                                              |
| `storage`              | `storage`             | Unchanged                                                            |
| `storageKey`           | `storageKey`          | Unchanged                                                            |
| `preferredWallets`     | -                     | Removed                                                              |
| `walletFilter`         | -                     | Removed (wallets filtered by network compatibility)                  |
| `theme`                | -                     | Removed (UI components are now web components with built-in styling) |
| -                      | `walletInitializers`  | New option for registering custom wallets                            |

### Step 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 through `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

### Step 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 (for example, `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.

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

**Mutation example:**

```diff
- 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:

```tsx

	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>;
}
```

### Step 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:

```diff
- 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:

```tsx

	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]);
	// ...
}
```

### Step 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

> **Warning:** The `reportTransactionEffects` feature is planned for deprecation in the [Wallet
> Standard](https://docs.sui.io/standards/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:

```diff
- 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](/dapp-kit/theming) for details on customizing the
appearance of dApp kit components.

**Quick theme setup:**

```css
: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:

```bash
npm uninstall @tanstack/react-query
```