diff --git a/.changeset/rude-wasps-divide.md b/.changeset/rude-wasps-divide.md new file mode 100644 index 0000000000000..980d1552fd385 --- /dev/null +++ b/.changeset/rude-wasps-divide.md @@ -0,0 +1,12 @@ +--- +'@mysten/dapp-kit': minor +--- + +Add global connection status info and change the hook interface of `useCurrentWallet` to +return an object to encapsulate connection info together. To migrate: + +Before: +const currentWallet = useCurrentWallet(); + +After: +const { currentWallet } = useCurrentWallet(); diff --git a/sdk/dapp-kit/src/components/WalletProvider.tsx b/sdk/dapp-kit/src/components/WalletProvider.tsx index f1ad9486fc754..e7395d846a110 100644 --- a/sdk/dapp-kit/src/components/WalletProvider.tsx +++ b/sdk/dapp-kit/src/components/WalletProvider.tsx @@ -65,6 +65,7 @@ export function WalletProvider({ wallets: getRegisteredWallets(preferredWallets, requiredFeatures), storageKey, storage, + autoConnect, }), ); diff --git a/sdk/dapp-kit/src/hooks/wallet/useAutoConnectWallet.ts b/sdk/dapp-kit/src/hooks/wallet/useAutoConnectWallet.ts index 05c090d43aebf..30810af95351a 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useAutoConnectWallet.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useAutoConnectWallet.ts @@ -4,31 +4,48 @@ import { useEffect } from 'react'; import { useConnectWallet } from './useConnectWallet.js'; +import { useCurrentWallet } from './useCurrentWallet.js'; import { useWallets } from './useWallets.js'; import { useWalletStore } from './useWalletStore.js'; export function useAutoConnectWallet(autoConnectEnabled: boolean) { const { mutate: connectWallet } = useConnectWallet(); - const wallets = useWallets(); + const setAutoConnectionStatus = useWalletStore((state) => state.setAutoConnectionStatus); const lastConnectedWalletName = useWalletStore((state) => state.lastConnectedWalletName); const lastConnectedAccountAddress = useWalletStore((state) => state.lastConnectedAccountAddress); + const wallets = useWallets(); + const { isDisconnected } = useCurrentWallet(); useEffect(() => { - if (!autoConnectEnabled || !lastConnectedWalletName) return; + if ( + !autoConnectEnabled || + !lastConnectedWalletName || + !lastConnectedAccountAddress || + !isDisconnected + ) { + return; + } const wallet = wallets.find((wallet) => wallet.name === lastConnectedWalletName); if (wallet) { - connectWallet({ - wallet, - accountAddress: lastConnectedAccountAddress || undefined, - silent: true, - }); + connectWallet( + { + wallet, + accountAddress: lastConnectedAccountAddress, + silent: true, + }, + { + onSettled: () => setAutoConnectionStatus('settled'), + }, + ); } }, [ autoConnectEnabled, connectWallet, + isDisconnected, lastConnectedAccountAddress, lastConnectedWalletName, + setAutoConnectionStatus, wallets, ]); } diff --git a/sdk/dapp-kit/src/hooks/wallet/useAutoConnectionStatus.ts b/sdk/dapp-kit/src/hooks/wallet/useAutoConnectionStatus.ts new file mode 100644 index 0000000000000..f8bc6d2fe0e3f --- /dev/null +++ b/sdk/dapp-kit/src/hooks/wallet/useAutoConnectionStatus.ts @@ -0,0 +1,12 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import { useWalletStore } from './useWalletStore.js'; + +/** + * Retrieves the status for the initial wallet auto-connection process. + */ +export function useAutoConnectionStatus() { + // TODO: Replace this with shareable mutation state once we require react-query v5 + return useWalletStore((state) => state.autoConnectionStatus); +} diff --git a/sdk/dapp-kit/src/hooks/wallet/useConnectWallet.ts b/sdk/dapp-kit/src/hooks/wallet/useConnectWallet.ts index a2bb54e693fba..18de2d73ec366 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useConnectWallet.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useConnectWallet.ts @@ -36,18 +36,27 @@ export function useConnectWallet({ ...mutationOptions }: UseConnectWalletMutationOptions = {}) { const setWalletConnected = useWalletStore((state) => state.setWalletConnected); + const setConnectionStatus = useWalletStore((state) => state.setConnectionStatus); return useMutation({ mutationKey: walletMutationKeys.connectWallet(mutationKey), - mutationFn: async ({ wallet, accountAddress, ...standardConnectInput }) => { - const connectResult = await wallet.features['standard:connect'].connect(standardConnectInput); - const connectedSuiAccounts = connectResult.accounts.filter((account) => - account.chains.some((chain) => chain.split(':')[0] === 'sui'), - ); - const selectedAccount = getSelectedAccount(connectedSuiAccounts, accountAddress); + mutationFn: async ({ wallet, accountAddress, ...connectArgs }) => { + try { + setConnectionStatus('connecting'); - setWalletConnected(wallet, connectedSuiAccounts, selectedAccount); - return { accounts: connectedSuiAccounts }; + const connectResult = await wallet.features['standard:connect'].connect(connectArgs); + const connectedSuiAccounts = connectResult.accounts.filter((account) => + account.chains.some((chain) => chain.split(':')[0] === 'sui'), + ); + const selectedAccount = getSelectedAccount(connectedSuiAccounts, accountAddress); + + setWalletConnected(wallet, connectedSuiAccounts, selectedAccount); + + return { accounts: connectedSuiAccounts }; + } catch (error) { + setConnectionStatus('disconnected'); + throw error; + } }, ...mutationOptions, }); diff --git a/sdk/dapp-kit/src/hooks/wallet/useCurrentWallet.ts b/sdk/dapp-kit/src/hooks/wallet/useCurrentWallet.ts index 667aca9870875..e47e89953f642 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useCurrentWallet.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useCurrentWallet.ts @@ -7,5 +7,34 @@ import { useWalletStore } from './useWalletStore.js'; * Retrieves the wallet that is currently connected to the dApp, if one exists. */ export function useCurrentWallet() { - return useWalletStore((state) => state.currentWallet); + const currentWallet = useWalletStore((state) => state.currentWallet); + const connectionStatus = useWalletStore((state) => state.connectionStatus); + + switch (connectionStatus) { + case 'connecting': + return { + connectionStatus, + currentWallet: null, + isDisconnected: false, + isConnecting: true, + isConnected: false, + } as const; + case 'disconnected': + return { + connectionStatus, + currentWallet: null, + isDisconnected: true, + isConnecting: false, + isConnected: false, + } as const; + case 'connected': { + return { + connectionStatus, + currentWallet: currentWallet!, + isDisconnected: false, + isConnecting: false, + isConnected: true, + } as const; + } + } } diff --git a/sdk/dapp-kit/src/hooks/wallet/useDisconnectWallet.ts b/sdk/dapp-kit/src/hooks/wallet/useDisconnectWallet.ts index 9eee6a1e71d64..2ad4f2865f2fc 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useDisconnectWallet.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useDisconnectWallet.ts @@ -23,7 +23,7 @@ export function useDisconnectWallet({ mutationKey, ...mutationOptions }: UseDisconnectWalletMutationOptions = {}) { - const currentWallet = useCurrentWallet(); + const { currentWallet } = useCurrentWallet(); const setWalletDisconnected = useWalletStore((state) => state.setWalletDisconnected); return useMutation({ diff --git a/sdk/dapp-kit/src/hooks/wallet/useSignAndExecuteTransactionBlock.ts b/sdk/dapp-kit/src/hooks/wallet/useSignAndExecuteTransactionBlock.ts index 461dd488c2ce7..9840392bbe27e 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useSignAndExecuteTransactionBlock.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useSignAndExecuteTransactionBlock.ts @@ -52,7 +52,7 @@ export function useSignAndExecuteTransactionBlock({ executeFromWallet, ...mutationOptions }: UseSignAndExecuteTransactionBlockMutationOptions = {}) { - const currentWallet = useCurrentWallet(); + const { currentWallet } = useCurrentWallet(); const currentAccount = useCurrentAccount(); const client = useSuiClient(); diff --git a/sdk/dapp-kit/src/hooks/wallet/useSignPersonalMessage.ts b/sdk/dapp-kit/src/hooks/wallet/useSignPersonalMessage.ts index 2d34832c30552..00a294da4285e 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useSignPersonalMessage.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useSignPersonalMessage.ts @@ -45,7 +45,7 @@ export function useSignPersonalMessage({ mutationKey, ...mutationOptions }: UseSignPersonalMessageMutationOptions = {}) { - const currentWallet = useCurrentWallet(); + const { currentWallet } = useCurrentWallet(); const currentAccount = useCurrentAccount(); return useMutation({ diff --git a/sdk/dapp-kit/src/hooks/wallet/useSignTransactionBlock.ts b/sdk/dapp-kit/src/hooks/wallet/useSignTransactionBlock.ts index b9bd332f8a041..f026b79c07138 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useSignTransactionBlock.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useSignTransactionBlock.ts @@ -45,7 +45,7 @@ export function useSignTransactionBlock({ mutationKey, ...mutationOptions }: UseSignTransactionBlockMutationOptions = {}) { - const currentWallet = useCurrentWallet(); + const { currentWallet } = useCurrentWallet(); const currentAccount = useCurrentAccount(); return useMutation({ diff --git a/sdk/dapp-kit/src/hooks/wallet/useSwitchAccount.ts b/sdk/dapp-kit/src/hooks/wallet/useSwitchAccount.ts index 11a87df94f179..ce5ea10ef64ef 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useSwitchAccount.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useSwitchAccount.ts @@ -30,7 +30,7 @@ export function useSwitchAccount({ mutationKey, ...mutationOptions }: UseSwitchAccountMutationOptions = {}) { - const currentWallet = useCurrentWallet(); + const { currentWallet } = useCurrentWallet(); const setAccountSwitched = useWalletStore((state) => state.setAccountSwitched); return useMutation({ diff --git a/sdk/dapp-kit/src/hooks/wallet/useWalletPropertiesChanged.ts b/sdk/dapp-kit/src/hooks/wallet/useWalletPropertiesChanged.ts index b828822c10cb0..2f47cd99d651c 100644 --- a/sdk/dapp-kit/src/hooks/wallet/useWalletPropertiesChanged.ts +++ b/sdk/dapp-kit/src/hooks/wallet/useWalletPropertiesChanged.ts @@ -10,7 +10,7 @@ import { useWalletStore } from './useWalletStore.js'; * Internal hook for easily handling various changes in properties for a wallet. */ export function useWalletPropertiesChanged() { - const currentWallet = useCurrentWallet(); + const { currentWallet } = useCurrentWallet(); const updateWalletAccounts = useWalletStore((state) => state.updateWalletAccounts); useEffect(() => { diff --git a/sdk/dapp-kit/src/index.ts b/sdk/dapp-kit/src/index.ts index a05b19e33045b..b39845fb036c4 100644 --- a/sdk/dapp-kit/src/index.ts +++ b/sdk/dapp-kit/src/index.ts @@ -13,6 +13,7 @@ export * from './hooks/useSuiClientInfiniteQuery.js'; export * from './hooks/useSuiClientMutation.js'; export * from './hooks/useSuiClientQuery.js'; export * from './hooks/wallet/useAccounts.js'; +export * from './hooks/wallet/useAutoConnectionStatus.js'; export * from './hooks/wallet/useConnectWallet.js'; export * from './hooks/wallet/useCurrentAccount.js'; export * from './hooks/wallet/useCurrentWallet.js'; diff --git a/sdk/dapp-kit/src/walletStore.ts b/sdk/dapp-kit/src/walletStore.ts index 75d1586b27169..3f20ef71c45ce 100644 --- a/sdk/dapp-kit/src/walletStore.ts +++ b/sdk/dapp-kit/src/walletStore.ts @@ -6,8 +6,14 @@ import { createStore } from 'zustand'; import type { StateStorage } from 'zustand/middleware'; import { createJSONStorage, persist } from 'zustand/middleware'; +type WalletConnectionStatus = 'disconnected' | 'connecting' | 'connected'; + +type WalletAutoConnectionStatus = 'disabled' | 'idle' | 'settled'; + export type WalletActions = { setAccountSwitched: (selectedAccount: WalletAccount) => void; + setConnectionStatus: (connectionStatus: WalletConnectionStatus) => void; + setAutoConnectionStatus: (autoConnectionStatus: WalletAutoConnectionStatus) => void; setWalletConnected: ( wallet: WalletWithRequiredFeatures, connectedAccounts: readonly WalletAccount[], @@ -31,15 +37,23 @@ export type StoreState = { currentAccount: WalletAccount | null; lastConnectedAccountAddress: string | null; lastConnectedWalletName: string | null; + connectionStatus: WalletConnectionStatus; + autoConnectionStatus: WalletAutoConnectionStatus; } & WalletActions; -export type WalletConfiguration = { +type WalletConfiguration = { wallets: WalletWithRequiredFeatures[]; + autoConnect: boolean; storage: StateStorage; storageKey: string; }; -export function createWalletStore({ wallets, storage, storageKey }: WalletConfiguration) { +export function createWalletStore({ + wallets, + storage, + storageKey, + autoConnect, +}: WalletConfiguration) { return createStore()( persist( (set, get) => ({ @@ -50,6 +64,17 @@ export function createWalletStore({ wallets, storage, storageKey }: WalletConfig lastConnectedAccountAddress: null, lastConnectedWalletName: null, connectionStatus: 'disconnected', + autoConnectionStatus: autoConnect ? 'idle' : 'disabled', + setConnectionStatus(connectionStatus) { + set(() => ({ + connectionStatus, + })); + }, + setAutoConnectionStatus(autoConnectionStatus) { + set(() => ({ + autoConnectionStatus, + })); + }, setWalletConnected(wallet, connectedAccounts, selectedAccount) { set(() => ({ accounts: connectedAccounts, @@ -57,6 +82,7 @@ export function createWalletStore({ wallets, storage, storageKey }: WalletConfig currentAccount: selectedAccount, lastConnectedWalletName: wallet.name, lastConnectedAccountAddress: selectedAccount?.address, + connectionStatus: 'connected', })); }, setWalletDisconnected() { @@ -66,6 +92,7 @@ export function createWalletStore({ wallets, storage, storageKey }: WalletConfig currentAccount: null, lastConnectedWalletName: null, lastConnectedAccountAddress: null, + connectionStatus: 'disconnected', })); }, setAccountSwitched(selectedAccount) { @@ -86,6 +113,7 @@ export function createWalletStore({ wallets, storage, storageKey }: WalletConfig currentAccount: null, lastConnectedWalletName: null, lastConnectedAccountAddress: null, + connectionStatus: 'disconnected', })); } else { set(() => ({ wallets: updatedWallets })); diff --git a/sdk/dapp-kit/test/components/WalletProvider.test.tsx b/sdk/dapp-kit/test/components/WalletProvider.test.tsx index 0743e5789b77d..0204b9470905f 100644 --- a/sdk/dapp-kit/test/components/WalletProvider.test.tsx +++ b/sdk/dapp-kit/test/components/WalletProvider.test.tsx @@ -27,7 +27,7 @@ describe('WalletProvider', () => { { wrapper }, ); - expect(result.current.currentWallet).toBeFalsy(); + expect(result.current.currentWallet.isConnected).toBeFalsy(); expect(result.current.currentAccount).toBeFalsy(); expect(result.current.wallets).toHaveLength(0); }); @@ -131,7 +131,6 @@ describe('WalletProvider', () => { () => ({ connectWallet: useConnectWallet(), currentAccount: useCurrentAccount(), - currentWallet: useCurrentWallet(), accounts: useAccounts(), }), { wrapper }, @@ -186,8 +185,10 @@ describe('WalletProvider', () => { { wrapper }, ); - await waitFor(() => expect(updatedResult.current.currentWallet).toBeTruthy()); - expect(updatedResult.current.currentWallet!.name).toStrictEqual('Mock Wallet 1'); + await waitFor(() => expect(updatedResult.current.currentWallet.isConnected).toBe(true)); + expect(updatedResult.current.currentWallet.currentWallet!.name).toStrictEqual( + 'Mock Wallet 1', + ); expect(updatedResult.current.currentAccount).toBeTruthy(); expect(updatedResult.current.currentAccount!.address).toStrictEqual( @@ -209,7 +210,6 @@ describe('WalletProvider', () => { () => ({ connectWallet: useConnectWallet(), disconnectWallet: useDisconnectWallet(), - currentWallet: useCurrentWallet(), currentAccount: useCurrentAccount(), }), { wrapper }, @@ -229,7 +229,7 @@ describe('WalletProvider', () => { // Render our component tree again and assert that we weren't able to auto-connect. const { result: updatedResult } = renderHook(() => useCurrentWallet(), { wrapper }); - expect(updatedResult.current).toBeFalsy(); + expect(updatedResult.current.isConnected).toBeFalsy(); act(() => unregister()); }); diff --git a/sdk/dapp-kit/test/hooks/useAutoConnectionStatus.test.tsx b/sdk/dapp-kit/test/hooks/useAutoConnectionStatus.test.tsx new file mode 100644 index 0000000000000..4a0f077d198c6 --- /dev/null +++ b/sdk/dapp-kit/test/hooks/useAutoConnectionStatus.test.tsx @@ -0,0 +1,55 @@ +// Copyright (c) Mysten Labs, Inc. +// SPDX-License-Identifier: Apache-2.0 + +import { act, renderHook, waitFor } from '@testing-library/react'; + +import { useAutoConnectionStatus } from '../../src/hooks/wallet/useAutoConnectionStatus.js'; +import { useConnectWallet } from '../../src/index.js'; +import { createMockAccount } from '../mocks/mockAccount.js'; +import { suiFeatures } from '../mocks/mockFeatures.js'; +import { createWalletProviderContextWrapper, registerMockWallet } from '../test-utils.js'; + +describe('useAutoConnectStatus', () => { + test('returns "disabled" when the auto-connect functionality is disabled', async () => { + const wrapper = createWalletProviderContextWrapper(); + const { result } = renderHook(() => useAutoConnectionStatus(), { wrapper }); + expect(result.current).toBe('disabled'); + }); + + test(`returns "idle" when we haven't yet made an auto-connection attempt`, async () => { + const wrapper = createWalletProviderContextWrapper({ autoConnect: true }); + const { result } = renderHook(() => useAutoConnectionStatus(), { wrapper }); + expect(result.current).toBe('idle'); + }); + + test('returns "settled" when we have made a successful auto-connection attempt', async () => { + const { unregister, mockWallet } = registerMockWallet({ + walletName: 'Mock Wallet 1', + accounts: [createMockAccount(), createMockAccount()], + features: suiFeatures, + }); + + const wrapper = createWalletProviderContextWrapper({ + autoConnect: true, + }); + const { result, unmount } = renderHook(() => useConnectWallet(), { wrapper }); + + // Manually connect a wallet so we have a wallet to auto-connect to later. + result.current.mutate({ + wallet: mockWallet, + accountAddress: mockWallet.accounts[1].address, + }); + + await waitFor(() => expect(result.current.isSuccess).toBe(true)); + + // Now unmount our component tree to simulate someone leaving the page. + unmount(); + + // Render our component tree again and auto-connect to our previously connected wallet account. + const { result: updatedResult } = renderHook(() => useAutoConnectionStatus(), { wrapper }); + + await waitFor(() => expect(updatedResult.current).toBe('settled')); + + act(() => unregister()); + }); +}); diff --git a/sdk/dapp-kit/test/hooks/useConnectWallet.test.tsx b/sdk/dapp-kit/test/hooks/useConnectWallet.test.tsx index 5aa34ff13eaf2..77bfa26e06821 100644 --- a/sdk/dapp-kit/test/hooks/useConnectWallet.test.tsx +++ b/sdk/dapp-kit/test/hooks/useConnectWallet.test.tsx @@ -37,7 +37,7 @@ describe('useConnectWallet', () => { result.current.connectWallet.mutate({ wallet: mockWallet }); await waitFor(() => expect(result.current.connectWallet.isError).toBe(true)); - expect(result.current.currentWallet).toBeFalsy(); + expect(result.current.currentWallet.isDisconnected).toBe(true); expect(result.current.currentAccount).toBeFalsy(); act(() => { @@ -62,8 +62,8 @@ describe('useConnectWallet', () => { result.current.connectWallet.mutate({ wallet: mockWallet }); await waitFor(() => expect(result.current.connectWallet.isSuccess).toBe(true)); - expect(result.current.currentWallet).toBeTruthy(); - expect(result.current.currentWallet!.name).toBe('Mock Wallet 1'); + expect(result.current.currentWallet.isConnected).toBe(true); + expect(result.current.currentWallet.currentWallet!.name).toBe('Mock Wallet 1'); expect(result.current.accounts).toHaveLength(1); expect(result.current.currentAccount).toBeTruthy(); @@ -92,8 +92,8 @@ describe('useConnectWallet', () => { result.current.connectWallet.mutate({ wallet: mockWallet }); await waitFor(() => expect(result.current.connectWallet.isSuccess).toBe(true)); - expect(result.current.currentWallet).toBeTruthy(); - expect(result.current.currentWallet!.name).toBe('Mock Wallet 1'); + expect(result.current.currentWallet.isConnected).toBe(true); + expect(result.current.currentWallet.currentWallet!.name).toBe('Mock Wallet 1'); expect(result.current.accounts).toHaveLength(1); expect(result.current.currentAccount).toBeTruthy(); diff --git a/sdk/dapp-kit/test/hooks/useDisconnectWallet.test.tsx b/sdk/dapp-kit/test/hooks/useDisconnectWallet.test.tsx index 210150b6222f1..0da5602c603ca 100644 --- a/sdk/dapp-kit/test/hooks/useDisconnectWallet.test.tsx +++ b/sdk/dapp-kit/test/hooks/useDisconnectWallet.test.tsx @@ -39,13 +39,13 @@ describe('useDisconnectWallet', () => { result.current.connectWallet.mutate({ wallet: mockWallet }); await waitFor(() => expect(result.current.connectWallet.isSuccess).toBe(true)); - expect(result.current.currentWallet).toBeTruthy(); + expect(result.current.currentWallet.isConnected).toBe(true); expect(result.current.currentAccount).toBeTruthy(); result.current.disconnectWallet.mutate(); await waitFor(() => expect(result.current.disconnectWallet.isSuccess).toBe(true)); - expect(result.current.currentWallet).toBeFalsy(); + expect(result.current.currentWallet.isDisconnected).toBe(true); expect(result.current.currentAccount).toBeFalsy(); act(() => { diff --git a/sdk/docs/examples/wallet-hooks.tsx b/sdk/docs/examples/wallet-hooks.tsx index 6c74319e30725..b4c1557d84747 100644 --- a/sdk/docs/examples/wallet-hooks.tsx +++ b/sdk/docs/examples/wallet-hooks.tsx @@ -5,6 +5,7 @@ import { ConnectButton, SuiClientProvider, useAccounts, + useAutoConnectionStatus, useConnectWallet, useCurrentAccount, useCurrentWallet, @@ -19,7 +20,7 @@ import { import { getFullnodeUrl } from '@mysten/sui.js/client'; import { TransactionBlock } from '@mysten/sui.js/transactions'; import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { useEffect, useState } from 'react'; +import { ComponentProps, useEffect, useState } from 'react'; import '@mysten/dapp-kit/dist/index.css'; @@ -57,26 +58,26 @@ export const UseAccountsExample = withProviders(() => { }); export const UseCurrentWalletExample = withProviders(() => { - const wallet = useCurrentWallet(); + const { currentWallet, connectionStatus } = useCurrentWallet(); return (
- {!wallet ? ( -
No wallet connected
- ) : ( + {connectionStatus === 'connected' ? (

Current wallet:

-
Name: {wallet.name}
+
Name: {currentWallet.name}
Accounts:
    - {wallet.accounts.map((account) => ( + {currentWallet.accounts.map((account) => (
  • - {account.address}
  • ))}
+ ) : ( +
Connection status: ${connectionStatus}
)}
); @@ -99,6 +100,20 @@ export const UseCurrentAccountExample = withProviders(() => { ); }); +export const UseAutoConnectionStatusExample = withProviders( + () => { + const autoConnectionStatus = useAutoConnectionStatus(); + + return ( +
+ +
Auto-connection status: {autoConnectionStatus}
+
+ ); + }, + { autoConnect: true }, +); + export const UseConnectWalletExample = withProviders(() => { const wallets = useWallets(); const { mutate: connect } = useConnectWallet(); @@ -284,7 +299,10 @@ export const UseSignAndExecuteTransactionBlockExample = withProviders(() => { ); }); -function withProviders(Component: React.FunctionComponent) { +function withProviders( + Component: React.FunctionComponent, + walletProviderProps?: Omit, 'children'>, +) { // Work around server-side pre-rendering const queryClient = new QueryClient(); const networks = { @@ -304,7 +322,7 @@ function withProviders(Component: React.FunctionComponent) { return ( - + diff --git a/sdk/docs/pages/dapp-kit/wallet-hooks/_meta.json b/sdk/docs/pages/dapp-kit/wallet-hooks/_meta.json index ea8e7f290b850..ece7f6bda4113 100644 --- a/sdk/docs/pages/dapp-kit/wallet-hooks/_meta.json +++ b/sdk/docs/pages/dapp-kit/wallet-hooks/_meta.json @@ -3,6 +3,7 @@ "useAccounts": "useAccounts", "useCurrentWallet": "useCurrentWallet", "useCurrentAccount": "useCurrentAccount", + "useAutoConnectionStatus": "useAutoConnectionStatus", "useConnectWallet": "useConnectWallet", "useDisconnectWallet": "useDisconnectWallet", "useSwitchAccount": "useSwitchAccount", diff --git a/sdk/docs/pages/dapp-kit/wallet-hooks/useAutoConnectionStatus.mdx b/sdk/docs/pages/dapp-kit/wallet-hooks/useAutoConnectionStatus.mdx new file mode 100644 index 0000000000000..bce78dfd4116e --- /dev/null +++ b/sdk/docs/pages/dapp-kit/wallet-hooks/useAutoConnectionStatus.mdx @@ -0,0 +1,31 @@ +import { UseAutoConnectionStatusExample } from '../../../examples/wallet-hooks'; + +# `useAutoConnectionStatus` + +The `useAutoConnectionStatus` hook retrieves the status for the initial wallet auto-connection +process. + +```ts +import { ConnectButton, useAutoConnectionStatus } from '@mysten/dapp-kit'; + +function MyComponent() { + const autoConnectionStatus = useAutoConnectionStatus(); + + return ( +
+ +
Auto-connection status: {autoConnectionStatus}
+
+ ); +} +``` + +## Example + + + +## Auto-connection status properties + +- `disabled` - When the auto-connection functionality is disabled +- `idle` - When the initial auto-connection attempt hasn't been made yet +- `settled` - When an auto-connection attempt has been made diff --git a/sdk/docs/pages/dapp-kit/wallet-hooks/useCurrentWallet.mdx b/sdk/docs/pages/dapp-kit/wallet-hooks/useCurrentWallet.mdx index 487ada29a37ab..5f5ad04119595 100644 --- a/sdk/docs/pages/dapp-kit/wallet-hooks/useCurrentWallet.mdx +++ b/sdk/docs/pages/dapp-kit/wallet-hooks/useCurrentWallet.mdx @@ -9,26 +9,26 @@ exists. import { ConnectButton, useCurrentWallet } from '@mysten/dapp-kit'; function MyComponent() { - const wallet = useCurrentWallet(); + const { currentWallet, connectionStatus } = useCurrentWallet(); return (
- {!wallet ? ( -
No wallet connected
- ) : ( + {connectionStatus === 'connected' ? (

Current wallet:

-
Name: {wallet.name}
+
Name: {currentWallet.name}
Accounts:
    - {wallet.accounts.map((account) => ( + {currentWallet.accounts.map((account) => (
  • - {account.address}
  • ))}
+ ) : ( +
Connection status: ${connectionStatus}
)}
); @@ -49,3 +49,15 @@ function MyComponent() { [wallet-standard](https://github.com/wallet-standard/wallet-standard) features implemented by the wallet - `chains` - An array of chain identifiers that the wallet supports + +## Connection status properties + +- `connectionStatus` + + - `disconnected` - When no wallet connected to the dApp + - `connecting` - When a wallet connection attempt is in progress + - `connecting` - When a wallet is connected to the dApp + +- `isDisconnected` - A derived boolean from the status variable above, provided for convenience. +- `isConnecting` - A derived boolean from the status variable above, provided for convenience. +- `isConnected` - A derived boolean from the status variable above, provided for convenience.