Signing Messages
Relevant source files
The following files were used as context for generating this wiki page:The sui-svelte-wallet-kit provides a streamlined API for requesting cryptographic signatures of arbitrary messages from a user's connected Sui wallet. This feature is essential for dApps that need to verify user identity or ownership of an address without requiring an on-chain transaction. The primary functions for this are signMessage and canSignMessage.
This functionality abstracts the differences between various wallet implementations, providing a single, consistent interface. It intelligently detects which signing standard a wallet supports, whether it's the Wallet Standard sui:signMessage, the Enoki-compatible sui:signPersonalMessage, or legacy adapter-specific methods.
Sources: README.md:20-21, 80-81, src/lib/SuiModule/SuiModule.svelte:1134-1185
Core API
The message signing feature is exposed through two main functions exported from the library.
Sources: src/lib/SuiModule/index.d.ts:16-17, src/lib/index.d.ts:17-18
signMessage(message)
This asynchronous function prompts the user to sign a message with their connected wallet.
| Parameter | Type | Description |
|---|---|---|
message | string | Uint8Array | The message to be signed. If a string is provided, it will be UTF-8 encoded into a Uint8Array. |
Returns: Promise<SignMessageResult> - A promise that resolves to an object containing the signature and the message bytes.
The function will throw an error if no wallet is connected or if the connected wallet does not support any message signing feature.
Sources: src/lib/SuiModule/SuiModule.svelte:1134-1185, src/lib/SuiModule/types.ts:79-83
canSignMessage()
This synchronous function checks if the currently connected wallet has the capability to sign messages. It returns true if a signing method is available, and false otherwise. It is crucial to use this function to conditionally render UI elements for message signing, ensuring a good user experience by not showing options that the wallet does not support.
The check is performed by inspecting the wallet adapter for the presence and function type of sui:signMessage, sui:signPersonalMessage, or legacy signMessage/signPersonalMessage methods.
Sources: src/lib/SuiModule/SuiModule.svelte:1187-1202, src/routes/+page.svelte:532-534
Signing Flow and Implementation
The signMessage function follows a specific sequence to request a signature, ensuring compatibility across different wallet standards.
This sequence diagram illustrates the interaction between the dApp, the wallet kit, and the user's wallet.
Method Prioritization
To maximize compatibility, signMessage attempts to use available signing methods in a specific order of preference. This logic is encapsulated within the function and is not exposed to the developer.
The following flowchart shows the internal decision process for selecting a signing method.
This diagram shows that the Wallet Standard feature sui:signMessage is preferred, followed by sui:signPersonalMessage (often used by zkLogin/Enoki wallets), and finally a legacy adapter-specific method. If none are found, an error is thrown.
Sources: src/lib/SuiModule/SuiModule.svelte:1143-1185
Data Structures
The signing functions use specific types for parameters and return values, which are defined in the package.
Sources: src/lib/SuiModule/types.ts:68-83
SignMessageParams
This interface defines the object passed to the underlying wallet adapter's signing function.
| Field | Type | Description |
|---|---|---|
account | WalletAccount | The currently active account object. |
chain | string | The chain identifier (e.g., sui:mainnet). |
message | Uint8Array | The byte array of the message to sign. |
Sources: src/lib/SuiModule/types.ts:68-73
SignMessageResult
This interface defines the structure of the object returned upon a successful signing operation.
| Field | Type | Description |
|---|---|---|
signature | string | The base64-encoded signature of the message. |
messageBytes | string | The hex-encoded string of the original message bytes. |
Sources: src/lib/SuiModule/types.ts:79-83
Usage Example
The following Svelte code demonstrates how to implement message signing in a component. It uses canSignMessage to conditionally show the signing UI and handles the asynchronous call to signMessage.
<script lang="ts">
import { canSignMessage, signMessage, useCurrentAccount } from 'sui-svelte-wallet-kit';
import type { SignMessageResult } from 'sui-svelte-wallet-kit';
let account = $derived(useCurrentAccount());
let message = $state('Hello, Sui blockchain!');
let signatureResult = $state<SignMessageResult | null>(null);
let isSigningMessage = $state(false);
let error = $state<string | null>(null);
const testSignMessage = async () => {
if (!account) {
error = 'Please connect your wallet first';
return;
}
isSigningMessage = true;
error = null;
signatureResult = null;
try {
signatureResult = await signMessage(message);
} catch (err: any) {
error = err?.message || 'Message signing failed';
} finally {
isSigningMessage = false;
}
};
</script>
{#if account}
{#if canSignMessage()}
<input bind:value={message} placeholder="Enter message to sign" />
<button onclick={testSignMessage} disabled={isSigningMessage}>
{isSigningMessage ? 'Signing Message...' : 'Sign Message'}
</button>
{:else}
<p>Current wallet does not support message signing.</p>
{/if}
{/if}
{#if signatureResult}
<p><strong>Signature:</strong> <code>{signatureResult.signature}</code></p>
{/if}
{#if error}
<p style="color:red">{error}</p>
{/if}
This example is adapted from the project's demonstration page and README.
Sources: src/routes/+page.svelte:124-138, 532-550, README.md:437-474
Summary
The message signing feature in sui-svelte-wallet-kit offers a powerful and simple way for dApps to request off-chain signatures. By using the signMessage and canSignMessage functions, developers can easily integrate this functionality while ensuring a robust and user-friendly experience. The library's abstraction layer handles the complexities of different wallet standards, allowing developers to focus on their application logic.
Sources: package.json:3, README.md:20-21