Fetching On-Chain Data (SuiNS & Balance)
Relevant source files
The following files were used as context for generating this wiki page:The sui-svelte-wallet-kit provides a streamlined and automated system for fetching essential on-chain data, specifically Sui Name Service (SuiNS) names and SUI coin balances. This functionality is primarily managed by the SuiModule component, which leverages Svelte 5's reactivity to keep the UI in sync with the user's on-chain assets. The system is designed to be efficient, with built-in caching and configurable behavior.
Data is exposed through a set of reactive stores, making it easy to integrate into any Svelte application. Developers can enable or disable automatic fetching and also have the ability to trigger manual refreshes, offering a balance between convenience and control.
Sources: README.md, src/lib/SuiModule/SuiModule.svelte
Core Architecture
The on-chain data fetching mechanism is built into the SuiModule.svelte component. It uses Svelte 5 runes ($state, $effect) to react to changes in the wallet's connection status and the currently active account. When an account is connected or switched, $effect hooks trigger the data fetching functions.
The module relies on two key dependencies for its operations:
@mysten/sui/client: Used to create aSuiClientinstance for interacting with the Sui network, primarily for fetching balances.@suiet/wallet-sdk: Provides theresolveAddressToSuiNSNamesutility for looking up SuiNS names associated with an address.
The entire process is designed to be mostly automatic, minimizing the boilerplate code required in the dApp.
Sources: src/lib/SuiModule/SuiModule.svelte:3-6, package.json:80-83
Data Flow Overview
The following diagram illustrates the high-level data flow for automatic data fetching upon a change in the active account.
This diagram shows how an account change within SuiModule triggers data fetching via external libraries, which in turn updates the reactive state stores consumed by the UI.
Sources: src/lib/SuiModule/SuiModule.svelte:1198-1221
Automatic Data Fetching
Automatic fetching is enabled by default but can be controlled via props on the SuiModule component.
| Prop | Type | Default | Description |
|---|---|---|---|
autoSuiNS | boolean | true | Automatically fetches SuiNS names on account change. |
autoSuiBalance | boolean | true | Automatically fetches SUI balance on account change. |
Sources: src/lib/SuiModule/SuiModule.svelte:1184-1188, README.md
This behavior is implemented using two separate $effect hooks within SuiModule.svelte. Each effect tracks the active account's address and chain. If either changes, the corresponding fetch function is invoked.
// src/lib/SuiModule/SuiModule.svelte:1209-1221
$effect(() => {
if (_suiNSInternalUpdate) return; // avoid duplicate fetch after label reassign
const key = account.value ? `${account.value.address}|${account.value.chains?.[0] ?? ''}` : '';
if (_autoFetchSuiNS && key && key !== _lastRefreshKey) {
// ... call refreshSuiNamesForAll() or refreshSuiNamesForActive()
}
});
$effect(() => {
if (!_autoFetchBalance) return;
const addr = account.value?.address;
// ...
if (key !== _lastBalanceKey) {
refreshSuiBalance(addr);
}
});
Sources: src/lib/SuiModule/SuiModule.svelte:1209-1221
SuiNS (Sui Name Service) Fetching
The kit automatically resolves SuiNS names for connected accounts.
Logic and Flow
- Initial Fetch: Upon the first connection, the
refreshSuiNamesForAllfunction is called. It fetches names for the active account and all other available accounts in the wallet, populating thesuiNamesByAddresscache. - Subsequent Fetches: When the user switches between already-seen accounts, the
refreshSuiNamesForActivefunction is called, which is a lighter operation that only fetches names for the newly active account. - Automatic Labeling: If a connected account does not have a
label, the system will automatically assign the first fetched SuiNS name as its label. This is done in-place to update the account object.
Sources: src/lib/SuiModule/SuiModule.svelte:449-468, 501-542
State Management
SuiNS data is managed through three reactive stores:
| Store | Type | Description |
|---|---|---|
suiNames | ReadableStore<string[]> | An array of SuiNS names for the currently active account. |
suiNamesLoading | ReadableStore<boolean> | A boolean flag indicating if a SuiNS fetch is in progress. |
suiNamesByAddress | ReadableStore<Record<string, string[]>> | A cache mapping Sui addresses to their array of SuiNS names. |
Sources: src/lib/SuiModule/SuiModule.svelte:614-628, 646-650, src/lib/SuiModule/index.d.ts:22-24
Sequence Diagram: SuiNS Fetch
This diagram shows the sequence of events when an active account changes.
SUI Balance Fetching
The kit also handles fetching the SUI coin balance for the active account.
Logic and Caching
The refreshSuiBalance function is the core of this feature. It can be called manually by the application or is triggered automatically by the $effect hook.
It includes a robust caching mechanism to prevent redundant API calls:
- Time-to-Live (TTL): A balance fetch is considered "fresh" for a default of 2000ms. Subsequent calls within this window will return the cached value unless forced. This default can be changed globally using
setSuiBalanceCacheTTL(ms). - Forced Refresh: The cache can be bypassed by calling
refreshSuiBalance(address, { force: true }). - Request Deduplication: If multiple calls to
refreshSuiBalancefor the same address are made concurrently, only one actual network request is sent. Subsequent callers receive the promise from the in-flight request.
Sources: src/lib/SuiModule/SuiModule.svelte:474-500, src/lib/SuiModule/types.ts:133-136
State Management
SUI balance data is managed through three reactive stores:
| Store | Type | Description |
|---|---|---|
suiBalance | ReadableStore<string | null> | The SUI balance for the currently active account as a string, or null. |
suiBalanceLoading | ReadableStore<boolean> | A boolean flag indicating if a balance fetch is in progress. |
suiBalanceByAddress | ReadableStore<Record<string, string>> | A cache mapping Sui addresses to their SUI balance string. |
Sources: src/lib/SuiModule/SuiModule.svelte:630-644, src/lib/SuiModule/index.d.ts:25-27
Sequence Diagram: Balance Fetch with Caching
This diagram illustrates how refreshSuiBalance uses its caching logic.
API and Usage
Below is a summary of the public API related to fetching on-chain data.
Functions
| Function | Parameters | Returns | Description |
|---|---|---|---|
refreshSuiBalance | address: string, options?: { force?: boolean, ttlMs?: number } | Promise<string|null> | Manually fetches or refreshes the SUI balance for a given address. |
setSuiBalanceCacheTTL | ms: number | void | Sets the global default cache TTL for SUI balance fetches in milliseconds. |
Sources: src/lib/SuiModule/index.d.ts:28, 32, src/lib/SuiModule/SuiModule.svelte:471-500, 502-505
Reactive Stores
| Store | Description |
|---|---|
suiNames | An array of SuiNS names for the current account. |
suiNamesLoading | A boolean loading state for the SuiNS fetch. |
suiNamesByAddress | A cache of SuiNS names, keyed by address. |
suiBalance | The SUI balance string for the current account. |
suiBalanceLoading | A boolean loading state for the balance fetch. |
suiBalanceByAddress | A cache of SUI balances, keyed by address. |
Sources: src/lib/SuiModule/index.d.ts:22-27, src/lib/index.d.ts:23-28
Example Usage
The following example from the project's demo page shows how to display SuiNS names and balance, and how to use the manual refresh button.
<!-- src/routes/+page.svelte -->
<script lang="ts">
import {
suiNames,
suiNamesLoading,
suiBalance,
suiBalanceLoading,
refreshSuiBalance,
useCurrentAccount
} from '$lib';
const account = $derived(useCurrentAccount());
const formatSui = (balance: string | null | undefined): string => {
// ... formatting logic ...
};
</script>
{#if account}
<!-- SuiNS Display -->
{#if suiNamesLoading.value}
<p><strong>SuiNS Names:</strong> Loading...</p>
{:else}
<p>
<strong>SuiNS Names:</strong>
{Array.isArray(suiNames.value) && suiNames.value.length > 0
? suiNames.value.join(', ')
: 'N/A'}
</p>
{/if}
<!-- Balance Display and Refresh -->
<div class="balance-box">
<h3>SUI Balance</h3>
<p>
{#if suiBalanceLoading.value}
Loading...
{:else}
<strong>{formatSui(suiBalance.value || '0')}</strong> SUI
{/if}
</p>
<button
class="action-btn"
onclick={() => {
if (account) refreshSuiBalance(account.address);
}}
disabled={!account || suiBalanceLoading.value}
>
Refresh Balance
</button>
</div>
{/if}
Sources: src/routes/+page.svelte:17-29, 60-70, 345-354, 375-395
Conclusion
The sui-svelte-wallet-kit offers a powerful and developer-friendly system for fetching and managing on-chain data. By automating SuiNS and balance lookups and providing simple reactive stores, it significantly reduces the effort required to build data-aware dApps. The inclusion of features like caching, request deduplication, and manual refresh controls demonstrates a thoughtful architecture that prioritizes both performance and flexibility.
Sources: README.md, src/lib/SuiModule/SuiModule.svelte