Skip to main content

Hana Wallet EVM Integration Guide

Guide for developers to integrate Hana Wallet with EVM dApps, including detection, connection, signing, and EIP-6963 support.

David avatar
Written by David
Updated over a month ago

Detecting Hana Wallet

Basic Detection

Hana Wallet injects an Ethereum provider into the webpage when an EVM chain is enabled. To detect if Hana Wallet is available:

if (window.hanaWallet?.available) {
console.log(`Hana Wallet detected! Version: ${window.hanaWallet.version}`);
} else {
console.log("Hana Wallet is not available. Please install Hana Wallet extension.");
}

Provider Selection

Hana Wallet coexists with other wallet providers like MetaMask. Here's how to properly detect and select Hana's provider:

function getEthereumProvider() {
if (window.hanaWallet?.available && window.hanaWallet.ethereum) {
console.log("Using Hana Wallet's Ethereum provider");
return window.hanaWallet.ethereum;
}

if (window.ethereum?.isHanaWallet) {
console.log("Using Hana Wallet via window.ethereum");
return window.ethereum;
}

if (window.ethereum) {
console.log("Using another Ethereum provider");
return window.ethereum;
}

console.error("No Ethereum provider detected");
return null;
}

const ethereumProvider = getEthereumProvider();

Core Functionality

Connecting to User's Wallet

To request access to the user's Ethereum accounts:

async function connectWallet(ethereumProvider) {
try {
const accounts = await ethereumProvider.request({ method: 'eth_requestAccounts' });
const userAddress = accounts[0];
console.log(`Connected to wallet with address: ${userAddress}`);
return userAddress;
} catch (error) {
console.error(`Connection failed: ${error.message}`);
return null;
}
}

Retrieving Connected Chain Information

async function getChainInfo(ethereumProvider) {
try {
const chainId = await ethereumProvider.request({ method: 'eth_chainId' });
const decimalChainId = parseInt(chainId, 16);
console.log(`Connected to chain ID: ${decimalChainId}`);
return decimalChainId;
} catch (error) {
console.error(`Failed to get chain info: ${error.message}`);
return null;
}
}

Signing a Message

async function signMessage(ethereumProvider, message, userAddress) {
try {
const msgHex = typeof message === 'string' && !message.startsWith('0x')
? `0x${Buffer.from(message).toString('hex')}`
: message;

const signature = await ethereumProvider.request({
method: 'personal_sign',
params: [msgHex, userAddress],
});

console.log(`Message signed successfully`);
return signature;
} catch (error) {
console.error(`Signing failed: ${error.message}`);
return null;
}
}

Sending a Transaction

async function sendTransaction(ethereumProvider, txParams) {
try {
const txHash = await ethereumProvider.request({
method: 'eth_sendTransaction',
params: [txParams],
});

console.log(`Transaction sent: ${txHash}`);
return txHash;
} catch (error) {
console.error(`Transaction failed: ${error.message}`);
return null;
}
}

const txParams = {
from: userAddress,
to: '0xRecipientAddress',
value: '0x' + (0.01 * 1e18).toString(16),
gas: '0x5208',
};

Advanced Integration

Handling Chain Changes

function setupChainListeners(ethereumProvider) {
ethereumProvider.on('chainChanged', (chainId) => {
console.log(`Chain changed to: ${parseInt(chainId, 16)}`);
window.location.reload();
});
}

Handling Account Changes

function setupAccountListeners(ethereumProvider) {
ethereumProvider.on('accountsChanged', (accounts) => {
if (accounts.length === 0) {
console.log('User disconnected all accounts');
} else {
console.log(`Active account changed to: ${accounts[0]}`);
}
});
}

EIP-6963 Support

Hana Wallet implements EIP-6963, the Multi Injected Provider Discovery standard, which provides a better way to handle multiple wallet extensions in the browser.

Benefits of EIP-6963

  • No Provider Conflicts: Eliminates conflicts when multiple wallet extensions are installed

  • Better User Experience: Users can choose which wallet to use for each dApp

  • Improved Security: Reduces risks from malicious extensions overriding wallet connections

Implementing EIP-6963 in Your dApp

const providers = [];

window.addEventListener('eip6963:announceProvider', (event) => {
const { info, provider } = event.detail;
console.log(`Wallet announced: ${info.name}, version ${info.version}`);
providers.push({ info, provider });

if (info.name.includes('Hana')) {
console.log('Hana Wallet detected via EIP-6963');
}
});

window.dispatchEvent(new Event('eip6963:requestProvider'));

function connectToWallet(selectedProviderIndex) {
const selectedProvider = providers[selectedProviderIndex].provider;
// Use selectedProvider for all Ethereum interactions
}

For a comprehensive implementation guide, refer to MetaMask's EIP-6963 Tutorial.

Complete Example

async function initializeHanaWalletIntegration() {
const ethereumProvider = getEthereumProvider();
if (!ethereumProvider) return;

setupChainListeners(ethereumProvider);
setupAccountListeners(ethereumProvider);

const userAddress = await connectWallet(ethereumProvider);
if (!userAddress) return;

const chainId = await getChainInfo(ethereumProvider);

document.getElementById('wallet-status').textContent = 'Connected';
document.getElementById('wallet-address').textContent = userAddress;
document.getElementById('chain-id').textContent = chainId;

document.getElementById('sign-button').addEventListener('click', async () => {
const message = "Welcome to our dApp!";
const signature = await signMessage(ethereumProvider, message, userAddress);
if (signature) {
document.getElementById('signature').textContent = signature;
}
});

document.getElementById('send-button').addEventListener('click', async () => {
const recipientAddress = document.getElementById('recipient').value;
const amount = document.getElementById('amount').value;

const txParams = {
from: userAddress,
to: recipientAddress,
value: '0x' + (parseFloat(amount) * 1e18).toString(16),
gas: '0x5208',
};

const txHash = await sendTransaction(ethereumProvider, txParams);
if (txHash) {
document.getElementById('tx-hash').textContent = txHash;
}
});
}

window.addEventListener('load', initializeHanaWalletIntegration);

Troubleshooting

Common Issues

  • Provider Not Found: Ensure Hana Wallet extension is installed and an EVM chain is active

  • Connection Rejected: User declined the connection request

  • Wrong Network: User is connected to a different network than expected

Provider State Check

function checkProviderState(ethereumProvider) {
if (!ethereumProvider) {
console.error("Provider not available");
return false;
}

if (!ethereumProvider.isConnected()) {
console.error("Provider not connected");
return false;
}

return true;
}

Further Resources

Did this answer your question?