Developer Document
Table of Contents
Quick navigation for the WOW EARN Wallet integration guide.
WOW EARN Wallet Integration Guide
Integrate the WOW EARN wallet button into your React application using RainbowKit and wagmi.
Table of Contents
Quick navigation for the WOW EARN Wallet integration guide.
Prerequisites
Before beginning implementation, ensure you have:
- Node.js and npm installed
- A React application set up
- Understanding of React, wallet connections, and Web3 concepts
- WalletConnect Project ID (obtain from WalletConnect Cloud)
Installation
Install the required dependencies:
$ npm install @rainbow-me/rainbowkit wagmi viem @tanstack/react-query
Setting Up the WOW Chain Configuration
Create chains.js and define the WOW chain configuration:
export const wowChain = {
id: 1916,
name: "WOW",
nativeCurrency: { name: "WOW", symbol: "WOW", decimals: 18 },
rpcUrls: {
default: { http: ["https://rpc.wowearn.io/"] },
public: { http: ["https://rpc.wowearn.io/"] },
},
blockExplorers: {
default: { name: "WOW Explorer", url: "https://wowearn.io/" },
},
testnet: false,
};Creating the WOW EARN Wallet Connector
Create wallets.js and define the WOW EARN wallet connector:
import { getWalletConnectConnector } from "@rainbow-me/rainbowkit";
export const wowEarnWallet = ({ projectId }) => ({
id: "wow-earn-wallet",
name: "WOW EARN Wallet",
iconUrl:
"https://media.licdn.com/dms/image/D4D0BAQGeS9ozbxH1iw/company-logo_200_200/0/1710776030038/",
iconBackground: "#0c2f78",
downloadUrls: {
android:
"https://play.google.com/store/apps/dev?id=8086605849401192032&hl=en_US",
ios:
"https://apps.apple.com/us/app/wow-earn-btc-crypto-wallet/id6443434220",
qrCode: "https://wowearn.com/download-wallet",
},
mobile: {
getUri: (uri) => `ullawallet://wc?uri=${encodeURIComponent(uri)}`,
},
qrCode: {
getUri: (uri) => uri,
instructions: {
learnMoreUrl: "https://wowearn.com/wallet-learn-more",
steps: [
{
step: "install",
title: "Open the WOW EARN Wallet application",
description:
"We recommend adding WOW EARN Wallet to your home screen for optimized access.",
},
{
step: "scan",
title: "Tap the scan button",
description:
"After scanning, a connection prompt will appear requesting authorization to connect your wallet.",
},
],
},
},
extension: {
instructions: {
learnMoreUrl: "https://wowearn.com/wallet-learn-more",
steps: [
{
step: "install",
title: "Install the WOW EARN Wallet extension",
description:
"We recommend pinning the WOW EARN Wallet extension to your browser toolbar for efficient access.",
},
{
step: "create",
title: "Create or Import a Wallet",
description:
"Ensure your wallet is secured with a robust backup solution. Never disclose your recovery phrase.",
},
{
step: "refresh",
title: "Refresh your browser",
description:
"Once wallet configuration is complete, refresh your browser to initialize the extension connection.",
},
],
},
},
createConnector: getWalletConnectConnector({ projectId }),
});Setting Up the Wagmi/RainbowKit Configuration
Create config.js that combines chain + wallet connector:
import { http } from "wagmi";
import { connectorsForWallets, getDefaultConfig } from "@rainbow-me/rainbowkit";
import { wowEarnWallet } from "./wallets";
import { wowChain } from "./chains";
// Replace with your WalletConnect project ID (use env var in production)
const projectId = "c9303d447e58d4f4156c7c8ab0ce7e31";
const connectors = connectorsForWallets(
[
{
groupName: "Recommended",
wallets: [wowEarnWallet],
},
],
{
appName: "WOW EARN Application",
projectId,
}
);
export const config = getDefaultConfig({
appName: "WOW EARN Application",
projectId,
chains: [wowChain],
connectors,
transports: {
[wowChain.id]: http("https://rpc.wowearn.io/"),
},
});Creating a Context Provider
Create WagmiContext.jsx to provide wallet context to your app:
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { WagmiProvider } from "wagmi";
import { RainbowKitProvider, darkTheme } from "@rainbow-me/rainbowkit";
import { config } from "./config";
export const WagmiContext = ({ children }) => {
const queryClient = new QueryClient();
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>
<RainbowKitProvider theme={darkTheme()} modalSize="compact">
{children}
</RainbowKitProvider>
</QueryClientProvider>
</WagmiProvider>
);
};Implementing the WOW EARN Wallet Button
Create a component for the wallet button in a file named WowWalletButton.jsx:
"use client";
import { useRef } from "react";
import { WalletButton } from "@rainbow-me/rainbowkit";
import { useAccount, useDisconnect } from "wagmi";
export function WowWalletButton() {
const walletButtonRef = useRef(null);
const { isConnected, address } = useAccount();
const { disconnect } = useDisconnect();
const formatAddress = (addr) => {
if (!addr) return "";
return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
};
const handleWalletConnect = (connect) => {
if (isConnected) disconnect();
else connect();
};
return (
<WalletButton.Custom wallet="wow-earn-wallet">
{({ ready, connect }) => (
<button
ref={walletButtonRef}
className="dropbtn font-semibold whitespace-nowrap"
onClick={() => handleWalletConnect(connect)}
disabled={!ready}
>
{isConnected ? formatAddress(address) : "Connect Today"}
</button>
)}
</WalletButton.Custom>
);
}Handling Connection State
You can extend your wallet button component to handle more advanced connection states and display additional information:
"use client";
import { useState, useRef, useEffect } from "react";
import { WalletButton } from "@rainbow-me/rainbowkit";
import { useAccount, useDisconnect } from "wagmi";
export function WowWalletButton() {
const walletButtonRef = useRef(null);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const { isConnected, address, chain } = useAccount();
const { disconnect } = useDisconnect();
const formatAddress = (addr) => {
if (!addr) return "";
return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
};
useEffect(() => {
function handleClickOutside(event) {
if (walletButtonRef.current && !walletButtonRef.current.contains(event.target)) {
setIsDropdownOpen(false);
}
}
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
const handleWalletConnect = (connect) => {
if (isConnected) setIsDropdownOpen((v) => !v);
else connect();
};
const handleDisconnect = () => {
disconnect();
setIsDropdownOpen(false);
};
return (
<div className="relative">
<WalletButton.Custom wallet="wow-earn-wallet">
{({ ready, connect }) => (
<button
ref={walletButtonRef}
className="dropbtn font-semibold whitespace-nowrap px-4 py-2 bg-blue-600 text-white rounded"
onClick={() => handleWalletConnect(connect)}
disabled={!ready}
>
{isConnected ? formatAddress(address) : "Connect Today"}
</button>
)}
</WalletButton.Custom>
{isConnected && isDropdownOpen && (
<div className="absolute right-0 mt-2 bg-white shadow-lg rounded p-2 z-10">
<div className="text-sm text-gray-700 mb-2">
Connected to {chain?.name || "Unknown Chain"}
</div>
<div className="text-xs text-gray-500 mb-3">
{formatAddress(address)}
</div>
<button
className="w-full text-left px-3 py-2 text-sm text-red-600 hover:bg-gray-100 rounded"
onClick={handleDisconnect}
>
Disconnect
</button>
</div>
)}
</div>
);
}Complete Implementation
Example integration in your app entry file:
"use client";
import { WagmiContext } from "./WagmiContext";
import { WowWalletButton } from "./WowWalletButton";
import "@rainbow-me/rainbowkit/styles.css";
export default function RootLayout({ children }) {
return (
<html lang="en">
<body>
<WagmiContext>
<header className="p-4 border-b">
<nav className="flex justify-between items-center">
<h1 className="text-xl font-bold">My Application</h1>
<WowWalletButton />
</nav>
</header>
<main>{children}</main>
</WagmiContext>
</body>
</html>
);
}Troubleshooting
Common Issues and Solutions:
- WalletConnect Project ID: Ensure you have a valid WalletConnect project ID from WalletConnect Cloud.
- Network Connectivity: Verify that the RPC URL for the WOW chain is accessible and properly configured.
- Wallet Connector: Confirm that the wallet ID (wow-earn-wallet) is correctly passed to the WalletButton.Custom component.
- Styling Customization: To match your application's design system, modify the CSS classes in the button component as needed.
- Translation Setup: If using internationalization, ensure proper setup of your translation library (i18next or equivalent).
Testing Recommendations:
To ensure proper integration, test the following:
- Connection process on both mobile and desktop devices
- Wallet state management (connected/disconnected)
- Chain switching functionality (if supporting multiple chains)
- UI responsiveness based on connection state changes
- Error handling for common connection failures
Accessing the Injected Provider
To interact with the WOW Wallet, you first need to access the injected provider. Use the following function to detect and retrieve the WOW Wallet provider:
javascript
function getWOWWalletFromWindow() {
const isWOWWallet = (ethereum) => {
return !!ethereum.isWOW;
};
const injectedProviderExist =
typeof window !== "undefined" && typeof window.ethereum !== "undefined";
if (!injectedProviderExist) {
return null;
}
if (isWOWWallet(window.ethereum)) {
return window.ethereum;
}
}
// Usage
const injectedProvider = getWOWWalletFromWindow();
Connecting to WOW Wallet
To establish a connection with the user's WOW Wallet, use the `eth_requestAccounts` method:
javascript
async function connectToWOWWallet() {
try {
const accounts = await injectedProvider.request({
method: "eth_requestAccounts",
});
console.log("Connected account:", accounts[0]);
return accounts[0];
} catch (error) {
if (error.code === 4001) {
console.error("User denied connection.");
} else {
console.error("An error occurred:", error);
}
return null;
}
}
Account Management Get Selected Account
To retrieve the currently selected account:
javascript
async function getSelectedAccount() {
const accounts = await injectedProvider.request({
method: "eth_accounts",
});
return accounts[0] || null;
}
Listen for Account Changes
To detect when the user changes accounts or disconnects:
javascript
function listenForAccountChanges(callback) {
injectedProvider.addListener("accountsChanged", (accounts) => {
if (accounts.length === 0) {
console.log("User disconnected.");
callback(null);
} else {
const newConnectedAccount = accounts[0];
console.log("New connected account:", newConnectedAccount);
callback(newConnectedAccount);
}
});
}
Chain Management Get Current Chain ID
async function getCurrentChainId() { const chainId = await injectedProvider.request({ method: "eth_chainId" }); return chainId; }
javascript
function listenForAccountChanges(callback) {
injectedProvider.addListener("accountsChanged", (accounts) => {
if (accounts.length === 0) {
console.log("User disconnected.");
callback(null);
} else {
const newConnectedAccount = accounts[0];
console.log("New connected account:", newConnectedAccount);
callback(newConnectedAccount);
}
});
}
Listen for Chain ID Changes
To detect when the user changes the network:
javascript
function listenForChainChanges(callback) {
injectedProvider.addListener("chainChanged", (chainId) => {
console.log("Chain changed to:", chainId);
callback(chainId);
});
}
Request Chain ID Change
To request a change to a specific network:
javascript
async function requestChainChange(chainId) {
try {
await injectedProvider.request({
method: "wallet_switchEthereumChain",
params: [{ chainId: chainId }],
});
console.log("Successfully switched to chain ID:", chainId);
} catch (error) {
if (error.code === 4902) {
console.log("Chain not added to wallet. Please add it first.");
} else if (error.code === 4001) {
console.log("User rejected the request.");
} else {
console.error("An error occurred:", error);
}
}
}
Sending Transactions
To send a transaction:
javascript
async function sendTransaction(transactionParameters) {
try {
const txHash = await injectedProvider.request({
method: "eth_sendTransaction",
params: [transactionParameters],
});
console.log("Transaction sent. Hash:", txHash);
return txHash;
} catch (error) {
console.error("Failed to send transaction:", error);
return null;
}
}
Usage example
javascript
const txParams = {
from: "0xb60e8dd61c5d32be8058bb8eb970870f07233155",
to: "0xd46e8dd67c5d32be8058bb8eb970870f07244567",
gas: "0x76c0", // 30400
gasPrice: "0x9184e72a000", // 10000000000000
value: "0x9184e72a", // 2441406250
data: "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",
};
sendTransaction(txParams);
Deep Linking
WOW Wallet supports deep linking for WalletConnect sessions. Use the following format:
ullawallet://wc?uri=YOUR_WALLETCONNECT_URI_HERE
Replace `YOUR_WALLETCONNECT_URI_HERE` with the actual WalletConnect URI, making sure to properly encode it.
This documentation should help developers integrate WOW Wallet into their applications. For further assistance or to report issues, please contact our support team.
