---
# System prepended metadata

title: 'Integrating Keplr Wallet with CosmWasm Smart Contracts: A Comprehensive Guide'

---

# Integrating Keplr Wallet and CosmWasm Smart Contracts: A Comprehensive Guide

## Table of Contents
1. [Prerequisites](#prerequisites)
2. [Project Setup](#project-setup)
3. [Keplr Wallet Integration](#keplr-wallet-integration)
4. [CosmWasm Contract Integration](#cosmwasm-contract-integration)
5. [Building the UI Components](#building-the-ui-components)
6. [Testing and Deployment](#testing-and-deployment)

## Prerequisites

Before starting, ensure you have the following installed:
- Node.js (v14 or higher)
- npm or yarn
- A CosmWasm-compatible blockchain network (e.g., Osmosis, Juno)
- Keplr wallet browser extension

## Project Setup

First, create a new React project using Create React App:

```bash
npx create-react-app keplr-cosmwasm-demo
cd keplr-cosmwasm-demo
npm install @keplr-wallet/types @cosmjs/cosmwasm-stargate @cosmjs/proto-signing
```

Create the following project structure:
```
src/
  ├── components/
  │   ├── WalletConnect.tsx
  │   ├── ContractInteraction.tsx
  │   └── TokenBalance.tsx
  ├── hooks/
  │   ├── useKeplr.ts
  │   └── useContract.ts
  ├── config/
  │   └── chain.ts
  └── App.tsx
```

## Keplr Wallet Integration

### 1. Chain Configuration

Create `src/config/chain.ts`:

```typescript
export const chainConfig = {
  chainId: "juno-1",
  chainName: "Juno",
  rpc: "https://rpc-juno.itastakers.com",
  rest: "https://lcd-juno.itastakers.com",
  bip44: {
    coinType: 118,
  },
  bech32Config: {
    bech32PrefixAccAddr: "juno",
    bech32PrefixAccPub: "junopub",
    bech32PrefixValAddr: "junovaloper",
    bech32PrefixValPub: "junovaloperpub",
    bech32PrefixConsAddr: "junovalcons",
    bech32PrefixConsPub: "junovalconspub",
  },
  currencies: [
    {
      coinDenom: "JUNO",
      coinMinimalDenom: "ujuno",
      coinDecimals: 6,
    },
  ],
  feeCurrencies: [
    {
      coinDenom: "JUNO",
      coinMinimalDenom: "ujuno",
      coinDecimals: 6,
    },
  ],
  stakeCurrency: {
    coinDenom: "JUNO",
    coinMinimalDenom: "ujuno",
    coinDecimals: 6,
  },
  gasPriceStep: {
    low: 0.01,
    average: 0.025,
    high: 0.04,
  },
};
```

### 2. Keplr Hook

Create `src/hooks/useKeplr.ts`:

```typescript
import { useState, useCallback } from 'react';
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';
import { chainConfig } from '../config/chain';

export const useKeplr = () => {
  const [address, setAddress] = useState<string>('');
  const [client, setClient] = useState<SigningCosmWasmClient | null>(null);

  const connect = useCallback(async () => {
    if (!window.keplr) {
      alert('Please install Keplr extension');
      return;
    }

    try {
      // Enable the chain in Keplr
      await window.keplr.enable(chainConfig.chainId);

      // Get the offlineSigner for signing transactions
      const offlineSigner = window.keplr.getOfflineSigner(chainConfig.chainId);

      // Get user address
      const accounts = await offlineSigner.getAccounts();
      setAddress(accounts[0].address);

      // Create signing client
      const client = await SigningCosmWasmClient.connectWithSigner(
        chainConfig.rpc,
        offlineSigner
      );
      setClient(client);
    } catch (error) {
      console.error('Error connecting to Keplr:', error);
      alert('Failed to connect to Keplr');
    }
  }, []);

  return { address, client, connect };
};
```

## CosmWasm Contract Integration

### 1. Contract Hook

Create `src/hooks/useContract.ts`:

```typescript
import { useCallback } from 'react';
import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';

export const useContract = (
  client: SigningCosmWasmClient | null,
  contractAddress: string
) => {
  const queryContract = useCallback(
    async (queryMsg: Record<string, unknown>) => {
      if (!client) return null;
      
      try {
        const result = await client.queryContractSmart(contractAddress, queryMsg);
        return result;
      } catch (error) {
        console.error('Error querying contract:', error);
        return null;
      }
    },
    [client, contractAddress]
  );

  const executeContract = useCallback(
    async (
      senderAddress: string,
      executeMsg: Record<string, unknown>,
      funds?: readonly Coin[]
    ) => {
      if (!client) return null;

      try {
        const result = await client.execute(
          senderAddress,
          contractAddress,
          executeMsg,
          'auto',
          undefined,
          funds
        );
        return result;
      } catch (error) {
        console.error('Error executing contract:', error);
        return null;
      }
    },
    [client, contractAddress]
  );

  return { queryContract, executeContract };
};
```

## Building the UI Components

### 1. Wallet Connect Component

Create `src/components/WalletConnect.tsx`:

```typescript
import React from 'react';
import { useKeplr } from '../hooks/useKeplr';

export const WalletConnect: React.FC = () => {
  const { address, connect } = useKeplr();

  return (
    <div>
      {!address ? (
        <button onClick={connect}>Connect Wallet</button>
      ) : (
        <div>
          <p>Connected Address: {address}</p>
        </div>
      )}
    </div>
  );
};
```

### 2. Contract Interaction Component

Create `src/components/ContractInteraction.tsx`:

```typescript
import React, { useState } from 'react';
import { useContract } from '../hooks/useContract';
import { useKeplr } from '../hooks/useKeplr';

interface ContractInteractionProps {
  contractAddress: string;
}

export const ContractInteraction: React.FC<ContractInteractionProps> = ({
  contractAddress,
}) => {
  const { address, client } = useKeplr();
  const { queryContract, executeContract } = useContract(client, contractAddress);
  const [queryResult, setQueryResult] = useState<any>(null);

  const handleQuery = async () => {
    const result = await queryContract({ 
      get_count: {} // Example query message
    });
    setQueryResult(result);
  };

  const handleExecute = async () => {
    if (!address) return;

    const result = await executeContract(
      address,
      { increment: {} }, // Example execute message
      []
    );
    
    if (result) {
      alert('Transaction successful!');
      handleQuery(); // Refresh the query result
    }
  };

  return (
    <div>
      <h2>Contract Interaction</h2>
      <button onClick={handleQuery}>Query Contract</button>
      {queryResult && (
        <pre>{JSON.stringify(queryResult, null, 2)}</pre>
      )}
      <button onClick={handleExecute} disabled={!address}>
        Execute Contract
      </button>
    </div>
  );
};
```

### 3. App Component

Update `src/App.tsx`:

```typescript
import React from 'react';
import { WalletConnect } from './components/WalletConnect';
import { ContractInteraction } from './components/ContractInteraction';

const CONTRACT_ADDRESS = 'your-contract-address-here';

function App() {
  return (
    <div className="App">
      <h1>Keplr + CosmWasm Demo</h1>
      <WalletConnect />
      <ContractInteraction contractAddress={CONTRACT_ADDRESS} />
    </div>
  );
}

export default App;
```

## Testing and Deployment

1. **Local Testing**

```bash
npm start
```

2. **Production Build**

```bash
npm run build
```

3. **Testing Checklist**
   - Wallet connection works
   - Contract queries return expected results
   - Contract executions complete successfully
   - Error handling works as expected
   - Transaction feedback is clear to users

## Error Handling Best Practices

1. Always check for Keplr availability:
```typescript
if (!window.keplr) {
  alert('Please install Keplr extension');
  return;
}
```

2. Handle transaction failures:
```typescript
try {
  const result = await executeContract(...);
  if (!result) throw new Error('Transaction failed');
  // Handle success
} catch (error) {
  console.error('Transaction error:', error);
  alert('Transaction failed: ' + error.message);
}
```

3. Implement loading states:
```typescript
const [isLoading, setIsLoading] = useState(false);

const handleTransaction = async () => {
  setIsLoading(true);
  try {
    await executeContract(...);
  } finally {
    setIsLoading(false);
  }
};
```

## Security Considerations

1. **Input Validation**: Always validate user input before sending it to the contract
2. **Gas Estimation**: Implement proper gas estimation for transactions
3. **Error Messages**: Don't expose sensitive information in error messages
4. **Transaction Confirmation**: Always wait for transaction confirmation before updating UI
5. **Network Security**: Use secure RPC endpoints and SSL/TLS connections

## Additional Features to Consider

1. **Transaction History**
2. **Balance Display**
3. **Network Selector**
4. **Gas Fee Customization**
5. **Contract Event Monitoring**

Remember to replace placeholder values like `your-contract-address-here` with actual values from your deployment.

For production applications, consider implementing additional features like:
- Loading indicators
- Better error handling
- Transaction history
- Network switching
- Gas fee customization

## Resources

- [Keplr Wallet Documentation](https://docs.keplr.app/)
- [CosmJS Documentation](https://cosmos.github.io/cosmjs/)
- [CosmWasm Documentation](https://docs.cosmwasm.com/)