State Management with Runes
Relevant source files
The following files were used as context for generating this wiki page:
The sui-svelte-wallet-kit leverages Svelte 5's new reactivity model, known as runes, to provide a simple and powerful state management solution. The core of the state management is centralized within the <script module> of the SuiModule.svelte component, which effectively creates a singleton state container for the entire application. This approach ensures that wallet connection status, account information, balances, and other data are globally accessible and reactive.
State is created using $state and side effects are managed with $effect. The module then exposes this state to consumer components through a series of exported functions and reactive objects, often styled as "hooks" (e.g., useCurrentAccount) or stores with a .value property. This allows developers to easily integrate reactive Sui wallet data into their Svelte 5 applications, as demonstrated in the project's README.md and the example usage in src/routes/+page.svelte.
Sources: src/lib/SuiModule/SuiModule.svelte:1-15, README.md:16-25
Core Architecture
The state management architecture is built upon a single Svelte module script. This script defines all the reactive state variables, derived computations, and side-effect logic required for the wallet kit's functionality.
Module-Level State
All primary state variables are defined using $state within the <script module lang="ts"> block of SuiModule.svelte. This makes them reactive primitives that can be updated, and any components that depend on them will automatically re-render.
The diagram below illustrates the flow from wallet discovery to state initialization and consumption.
This diagram shows how wallet discovery populates the connection modal. User interaction triggers the connect function, which updates the central $state variables. These state changes then trigger $effect hooks for data fetching and update the consumer UI through exported reactive hooks.
Sources: src/lib/SuiModule/SuiModule.svelte:17-60, 1018-1025, src/routes/+page.svelte:1-30
Key State Variables
The following table summarizes the most important module-level state variables defined in SuiModule.svelte.
| Variable | Type | Description |
|---|---|---|
walletAdapter | SuiWalletAdapter | undefined | The adapter for the currently connected wallet. |
status | ConnectionStatus | The current connection status (DISCONNECTED, CONNECTING, CONNECTED). |
_account | SuiAccount | undefined | The currently active Sui account object. |
_wallet | WalletWithStatus | undefined | Information about the currently connected wallet. |
_suiNames | string[] | An array of SuiNS names for the active account. |
_suiNamesByAddress | Record<string, string[]> | A cache of SuiNS names, keyed by address. |
_suiBalanceByAddress | Record<string, string> | A cache of SUI balances, keyed by address. |
_suiBalanceLoading | boolean | A flag indicating if a balance fetch is in progress. |
_accountsSnapshot | SuiAccount[] | A snapshot of all accounts available from the connected wallet. |
_lastWalletSelection | { wallet: Wallet; installed: boolean } | The last wallet the user selected from the modal. |
_zkLoginGoogle | ZkLoginGoogleConfig | null | Configuration for Enoki zkLogin. |
Sources: src/lib/SuiModule/SuiModule.svelte:17-60, src/lib/SuiModule/types.ts
Reactive Data Flow and Effects
The library uses $effect runes to react to state changes and perform side effects, such as fetching data from the Sui network or persisting connection information to localStorage.
Automatic Data Fetching
When the active account changes, $effect hooks are triggered to automatically fetch associated data like SuiNS names and SUI balance.
The sequence diagram below details this process.
This diagram shows that a call to switchAccount updates the _account state. An $effect in SuiModule.svelte observes this change and automatically calls functions to fetch the new account's SuiNS name and balance, which in turn update other state variables, causing the UI to reactively update.
Sources: src/lib/SuiModule/SuiModule.svelte:1062-1085
Auto-Connection
The kit supports auto-connecting to the last used wallet. This is managed by saving connection data to localStorage and using an $effect to attempt connection on component mount if autoConnect is enabled.
- Save Connection: After a successful connection,
saveConnectionDatais called to store the wallet name inlocalStorage. - Retrieve Connection: On initialization,
getConnectionDataretrieves this information. - Reactive Effect: An
$effecthook checks for available wallets and theautoConnectprop. If conditions are met, it callsautoConnectWallet, which finds the saved wallet among the available ones and connects to it.
Sources: src/lib/SuiModule/SuiModule.svelte:207-224, 1050-1060
Exposing State to Consumers
The internal state of SuiModule is exposed to the application through a set of exported functions and reactive objects. This provides a clean, "hook-based" API for consumers.
Exported Stores and "Hooks"
The primary way to access state is through exported functions that return the state value or objects that contain a .value getter. This pattern is idiomatic for Svelte 5 runes.
| Export | Type | Description |
|---|---|---|
useCurrentAccount() | () => SuiAccount | undefined | A function that returns the current reactive account object. |
useAccounts() | () => SuiAccount[] | A function that returns the reactive array of all available accounts. |
useCurrentWallet() | () => SuiWallet | undefined | A function that returns the current reactive wallet object. |
useSuiClient() | () => SuiClient | A function that returns a SuiClient instance for the current network. |
suiBalance | ReadableStore<string | null> | A reactive object with a .value property for the current account's balance. |
suiNames | SuiNamesStore<string[]> | A reactive object with a .value property for the current account's SuiNS names. |
accountLoading | ReadableStore<boolean> | A reactive object indicating if a connection is in progress. |
activeAccountIndex | ReadableStore<number> | A reactive object with the index of the currently active account. |
Sources: src/lib/SuiModule/index.d.ts:7-31, src/lib/SuiModule/SuiModule.svelte:612-717
Usage in Components
Consumer components, like the demo page at src/routes/+page.svelte, import these functions and use them to get reactive state. The $derived rune is often used to create computed values from this state.
<script lang="ts">
import {
useCurrentAccount,
useAccounts,
suiBalance,
suiNames,
} from '$lib';
// Use the "hook" to get a reactive reference to the account
const account = $derived(useCurrentAccount());
const accounts = $derived(useAccounts());
</script>
{#if account}
<!-- Accessing derived state -->
<p>Address: {account.address}</p>
<!-- Accessing a store-like object's value -->
<p>Balance: {suiBalance.value}</p>
<p>SuiNS Names: {suiNames.value.join(', ')}</p>
{/if}
This example from src/routes/+page.svelte and README.md shows how $derived is used with useCurrentAccount to get a reactive account variable. Other state, like suiBalance, is accessed directly via its .value property within the template.
Sources: src/routes/+page.svelte:29-32, 330-370, README.md:183-191
Data Structures
The state management revolves around a few key data structures defined in types.ts.
SuiAccount and SuiWallet
The SuiAccount and SuiWallet interfaces define the shape of the core data managed by the state.
This diagram illustrates the relationship between SuiWallet and SuiAccount, where a wallet can contain multiple accounts. These structures are compatible with the @wallet-standard/core types.
Sources: src/lib/SuiModule/types.ts:13-17, 431-450
Summary
The sui-svelte-wallet-kit implements a modern and efficient state management system using Svelte 5 runes. By centralizing state in a single module script and exposing it through a clean, hook-like API, it provides a developer-friendly way to build reactive dApps on the Sui blockchain. The use of $state for reactive primitives and $effect for handling side effects like data fetching and local storage persistence creates a robust and predictable data flow throughout the application.