Skip to main content
All CollectionsHana WalletDevelopers
Hana Wallet Sui Integration Guide

Hana Wallet Sui Integration Guide

Integrate Hana Wallet with your Sui dApp using @mysten/dapp-kit. Includes setup, connection, signing, and transaction handling.

David avatar
Written by David
Updated over a week ago

Hana Wallet is a versatile, multi-chain wallet that enables seamless interactions with decentralized applications (dApps) across various blockchain networks, including Sui.

πŸ’§ This guide provides comprehensive instructions for integrating Hana Wallet into your Sui-based applications using the @mysten/dapp-kit library.


Prerequisites

Before you begin, ensure your development environment includes:


Integration Guide

Step 1: Install Required Packages

npm install @mysten/dapp-kit @mysten/sui
  • @mysten/dapp-kit: React components and hooks for Sui dApp development

  • @mysten/sui: Sui TypeScript SDK for blockchain interactions


Step 2: Configure Providers

import React from 'react';
import ReactDOM from 'react-dom';
import '@mysten/dapp-kit/dist/index.css';
import { createNetworkConfig, SuiClientProvider, WalletProvider } from '@mysten/dapp-kit';
import { getFullnodeUrl } from '@mysten/sui/client';
import App from './App';

const { networkConfig } = createNetworkConfig({
localnet: { url: getFullnodeUrl('localnet') },
devnet: { url: getFullnodeUrl('devnet') },
testnet: { url: getFullnodeUrl('testnet') },
mainnet: { url: getFullnodeUrl('mainnet') },
});

ReactDOM.render(
<React.StrictMode>
<SuiClientProvider networks={networkConfig} defaultNetwork="mainnet">
<WalletProvider>
<App />
</WalletProvider>
</SuiClientProvider>
</React.StrictMode>,
document.getElementById('root')
);

Note: Set defaultNetwork to the appropriate environment for your dApp (e.g., mainnet or devnet).


Step 3: Implement Wallet Connection

import React from 'react';
import { useConnectWallet, useWallets, ConnectButton } from '@mysten/dapp-kit';

function WalletConnection() {
const wallets = useWallets();
const { mutate: connect } = useConnectWallet();

return (
<div className="wallet-connection">
<h2>Connect Your Wallet</h2>
<ConnectButton />
<div className="wallet-list">
{wallets.map((wallet) => (
<button
key={wallet.name}
onClick={() => connect({ wallet })}
className="wallet-button"
>
{wallet.icon && <img src={wallet.icon} alt={`${wallet.name} icon`} />}
Connect to {wallet.name}
</button>
))}
</div>
</div>
);
}

export default WalletConnection;

Step 4: Access Wallet Information

import React from 'react';
import { useCurrentAccount } from '@mysten/dapp-kit';

function AccountInfo() {
const currentAccount = useCurrentAccount();

if (!currentAccount) {
return <p className="account-status">No wallet connected</p>;
}

return (
<div className="account-info">
<h3>Connected Account</h3>
<div className="address-container">
<span className="label">Address:</span>
<code className="address">{currentAccount.address}</code>
</div>
{currentAccount.chains?.map(chain => (
<div key={chain} className="chain-info">
<span className="label">Chain:</span>
<span>{chain}</span>
</div>
))}
</div>
);
}

export default AccountInfo;

Step 5: Sign Personal Messages

import React, { useState } from 'react';
import { useSignPersonalMessage, useCurrentAccount } from '@mysten/dapp-kit';

function MessageSigning() {
const { mutate: signPersonalMessage, isPending } = useSignPersonalMessage();
const currentAccount = useCurrentAccount();
const [message, setMessage] = useState('Hello from my Sui dApp!');
const [signature, setSignature] = useState('');
const [error, setError] = useState('');

const handleSignMessage = () => {
if (!currentAccount) {
setError('Please connect your wallet first');
return;
}

setError('');
signPersonalMessage(
{ message: new TextEncoder().encode(message) },
{
onSuccess: (result) => {
setSignature(result.signature);
console.log('Full result:', result);
},
onError: (err) => {
setError(`Signing failed: ${err.message}`);
console.error('Signing error:', err);
},
}
);
};

return (
<div className="message-signing">
<h3>Sign Message</h3>
<textarea
id="message"
value={message}
onChange={(e) => setMessage(e.target.value)}
rows={3}
className="input-field"
/>
<button
onClick={handleSignMessage}
disabled={isPending || !currentAccount}
className="sign-button"
>
{isPending ? 'Signing...' : 'Sign Message'}
</button>
{error && <div className="error-message">{error}</div>}
{signature && (
<div className="signature-result">
<h4>Signature:</h4>
<code>{signature}</code>
</div>
)}
</div>
);
}

export default MessageSigning;

Step 6: Execute Transactions

import React, { useState } from 'react';
import { useSignAndExecuteTransaction, useCurrentAccount } from '@mysten/dapp-kit';
import { TransactionBlock } from '@mysten/sui/transactions';

function TransactionExecution() {
const { mutate: signAndExecuteTransaction, isPending } = useSignAndExecuteTransaction();
const currentAccount = useCurrentAccount();
const [txResult, setTxResult] = useState(null);
const [error, setError] = useState('');

const handleTransaction = async () => {
if (!currentAccount) {
setError('Please connect your wallet first');
return;
}

try {
const tx = new TransactionBlock();
const [coin] = tx.splitCoins(tx.gas, [tx.pure(1000000)]);
tx.transferObjects([coin], tx.pure(currentAccount.address));
tx.setGasBudget(10000000);

setError('');
signAndExecuteTransaction(
{ transactionBlock: tx },
{
onSuccess: (result) => {
setTxResult(result);
},
onError: (err) => {
setError(`Transaction failed: ${err.message}`);
},
}
);
} catch (err) {
setError(`Error creating transaction: ${err.message}`);
}
};

return (
<div className="transaction-execution">
<h3>Execute Transaction</h3>
<button
onClick={handleTransaction}
disabled={isPending || !currentAccount}
className="transaction-button"
>
{isPending ? 'Processing...' : 'Send Test Transaction'}
</button>
{error && <div className="error-message">{error}</div>}
{txResult && (
<div className="transaction-result">
<p><strong>Digest:</strong> <code>{txResult.digest}</code></p>
<p><strong>Status:</strong> <span>{txResult.effects?.status?.status}</span></p>
</div>
)}
</div>
);
}

export default TransactionExecution;

Step 7: Manage Wallet Disconnection

import React from 'react';
import { useDisconnectWallet, useCurrentAccount } from '@mysten/dapp-kit';

function WalletDisconnection() {
const { mutate: disconnect, isPending } = useDisconnectWallet();
const currentAccount = useCurrentAccount();

if (!currentAccount) return null;

return (
<div className="wallet-disconnection">
<button
onClick={() => disconnect()}
disabled={isPending}
className="disconnect-button"
>
{isPending ? 'Disconnecting...' : 'Disconnect Wallet'}
</button>
</div>
);
}

export default WalletDisconnection;

Step 8: Complete Example App

import React from 'react';
import WalletConnection from './components/WalletConnection';
import AccountInfo from './components/AccountInfo';
import MessageSigning from './components/MessageSigning';
import TransactionExecution from './components/TransactionExecution';
import WalletDisconnection from './components/WalletDisconnection';
import { useCurrentAccount } from '@mysten/dapp-kit';

function App() {
const currentAccount = useCurrentAccount();

return (
<div className="app-container">
<h1>Hana Wallet Integration Demo</h1>
<WalletConnection />
{currentAccount ? (
<>
<AccountInfo />
<MessageSigning />
<TransactionExecution />
<WalletDisconnection />
</>
) : (
<p>Connect your Hana Wallet to begin</p>
)}
</div>
);
}

export default App;

Advanced Features

Custom Network Configuration

const { networkConfig } = createNetworkConfig({
mainnet: {
url: "https://your-custom-rpc-endpoint.com",
faucetUrl: "https://faucet.your-service.com",
description: "Production Network"
},
});

Error Handling Example

try {
// wallet operation
} catch (error) {
if (error.code === 4001) {
setErrorMessage("Transaction was rejected.");
} else if (error.message.includes("insufficient funds")) {
setErrorMessage("Not enough SUI in your wallet.");
} else {
setErrorMessage(`An error occurred: ${error.message}`);
console.error(error);
}
}

Testing & Debugging

  • Use defaultNetwork="devnet" for testing

  • Get test tokens from the Sui Devnet Faucet

  • Ensure wallet and dApp are on the same network


Common Issues

Issue

Solution

Wallet not connecting

Ensure Hana Wallet is installed and unlocked

Transaction failed

Check gas budget and account balance

Signature errors

Verify the message format

Network mismatch

Ensure both dApp and wallet are on the same chain


Additional resources

Did this answer your question?