Important: Keplr Compatibility
Hana Wallet emulates the Keplr Wallet API.
If your dApp already integrates with Keplr Wallet, it will work with Hana Wallet with minimal or no changes.
Use window.keplr to interact with Hana Wallet. Hana injects itself as keplr in the browser window object and implements the Keplr interface.
Supported Chains
| Network | Mainnet | Testnet | 
| Cosmos Hub | cosmoshub-4 | theta-testnet-001 | 
| Osmosis | osmosis-1 | osmo-test-5 | 
| Neutron | neutron-1 | pion-1 | 
| Archway | archway-1 | constantine-3 | 
| Injective | injective-1 | injective-888 | 
To support other Cosmos chains, use the experimentalSuggestChain method.
Prerequisites
- A web application (React or other JavaScript framework) 
- Installed dependency: - @cosmjs/stargate
Basic Integration
1. Detecting Hana Wallet
const checkForHanaWallet = async () => {
  if (window.keplr) {
    console.log('Wallet detected');
    return true;
  } else {
    console.log('No wallet detected');
    return false;
  }
};
2. Connecting to a Chain
const connectToChain = async (chainId) => {
  if (!window.keplr) {
    alert("Please install Hana Wallet");
    return;
  }
  try {
    await window.keplr.enable(chainId);
    const offlineSigner = window.keplr.getOfflineSigner(chainId);
    const accounts = await offlineSigner.getAccounts();
    const address = accounts[0].address;
    console.log(`Connected to ${chainId} with address: ${address}`);
    return { offlineSigner, address };
  } catch (err) {
    console.error(`Failed to connect: ${err.message}`);
  }
};
3. Getting the User's Address
const getUserAddress = async (chainId) => {
  try {
    await window.keplr.enable(chainId);
    const key = await window.keplr.getKey(chainId);
    return key.bech32Address;
  } catch (err) {
    console.error(`Error getting address: ${err.message}`);
    throw err;
  }
};
4. Signing an Arbitrary Message
const signArbitraryMessage = async (chainId, address, message) => {
  try {
    await window.keplr.enable(chainId);
    const signature = await window.keplr.signArbitrary(chainId, address, message);
    console.log("Signature:", signature);
    return signature;
  } catch (err) {
    console.error(`Signing failed: ${err.message}`);
    throw err;
  }
};
5. Sending Tokens
const sendTokens = async (chainId, recipientAddress, amount) => {
  try {
    await window.keplr.enable(chainId);
    const offlineSigner = window.keplr.getOfflineSigner(chainId);
    const accounts = await offlineSigner.getAccounts();
    const senderAddress = accounts[0].address;
    let rpcEndpoint;
    if (chainId === "cosmoshub-4") {
      rpcEndpoint = "https://rpc.cosmos.network";
    } else if (chainId === "osmosis-1") {
      rpcEndpoint = "https://rpc.osmosis.zone";
    } else if (chainId === "neutron-1") {
      rpcEndpoint = "https://rpc-neutron.keplr.app";
    } else if (chainId === "archway-1") {
      rpcEndpoint = "https://rpc.mainnet.archway.io";
    } else if (chainId === "injective-1") {
      rpcEndpoint = "https://rpc-injective.keplr.app";
    }
    const client = await SigningStargateClient.connectWithSigner(rpcEndpoint, offlineSigner);
    let denom = "uatom";
    if (chainId.includes("osmosis")) {
      denom = "uosmo";
    } else if (chainId.includes("neutron")) {
      denom = "untrn";
    } else if (chainId.includes("archway")) {
      denom = "aarch";
    } else if (chainId.includes("injective")) {
      denom = "inj";
    }
    const amountToSend = {
      denom: denom,
      amount: amount,
    };
    const fee = {
      amount: [{ denom: denom, amount: "5000" }],
      gas: "200000",
    };
    const result = await client.sendTokens(senderAddress, recipientAddress, [amountToSend], fee, "");
    console.log("Transaction hash:", result.transactionHash);
    return result;
  } catch (err) {
    console.error(`Token transfer failed: ${err.message}`);
    throw err;
  }
};
Adding Custom Chains
const suggestChain = async (chainInfo) => {
  try {
    await window.keplr.experimentalSuggestChain(chainInfo);
    console.log(`Chain ${chainInfo.chainId} added successfully`);
    return true;
  } catch (err) {
    console.error(`Failed to add chain: ${err.message}`);
    throw err;
  }
};
Example chain info for Osmosis Testnet:
const osmosisTestnet = {
  chainId: "osmo-test-5",
  chainName: "Osmosis Testnet",
  rpc: "https://rpc.testnet.osmosis.zone",
  rest: "https://lcd.testnet.osmosis.zone",
  stakeCurrency: {
    coinDenom: "OSMO",
    coinMinimalDenom: "uosmo",
    coinDecimals: 6
  },
  bip44: {
    coinType: 118
  },
  bech32Config: {
    bech32PrefixAccAddr: "osmo",
    bech32PrefixAccPub: "osmopub",
    bech32PrefixValAddr: "osmovaloper",
    bech32PrefixValPub: "osmovaloperpub",
    bech32PrefixConsAddr: "osmovalcons",
    bech32PrefixConsPub: "osmovalconspub"
  },
  currencies: [
    {
      coinDenom: "OSMO",
      coinMinimalDenom: "uosmo",
      coinDecimals: 6
    }
  ],
  feeCurrencies: [
    {
      coinDenom: "OSMO",
      coinMinimalDenom: "uosmo",
      coinDecimals: 6,
      gasPriceStep: {
        low: 0.01,
        average: 0.025,
        high: 0.04
      }
    }
  ],
  coinType: 118,
  beta: true
};
Technical Details
Hana Wallet implements the following Keplr interfaces:
- getOfflineSigner: Returns a signer for Amino and Direct signing
- getOfflineSignerOnlyAmino: For Ledger compatibility
- getOfflineSignerAuto: Automatically chooses the right mode
- signAmino: Sign a transaction in Amino format
- signDirect: Sign in Direct signing format
- signArbitrary: Sign arbitrary messages (ADR-36)
- experimentalSuggestChain: Suggest new chains
Tips for dApp Developers
- Always use - enable()first before accessing account info
- Handle rejections and errors to give users clear feedback 
- Support multiple chains by dynamically adjusting denom and fees 
- Use reliable RPC endpoints per chain 
- Use - verifyArbitrary()on the backend if you care about verifying signatures

