-
Notifications
You must be signed in to change notification settings - Fork 180
fixed issue #180 Added Wallet Management & Connection Settings Page #181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| PRIVATE_KEY=<your_private_key> | ||
| RPC_URL_SEPOLIA=<your_sepolia_rpc_url> | ||
| RPC_URL_FUJI=<your_fuji_rpc_url> | ||
| ETHERSCAN_KEY=<your_etherscan_api_key> |
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,249 @@ | ||
| # Wallet Management Feature | ||
|
|
||
| ## 📋 Overview | ||
|
|
||
| A comprehensive Wallet Management page has been implemented for the Agora-Blockchain voting platform. This feature allows users to view, manage, and interact with their connected Web3 wallets. | ||
|
|
||
| ## ✨ Features Implemented | ||
|
|
||
| ### 1. **Wallet Connection & Display** | ||
| - Real-time wallet connection status | ||
| - Display of connected wallet address with copy-to-clipboard functionality | ||
| - Wallet connector identification (MetaMask, WalletConnect, Coinbase Wallet, etc.) | ||
| - ENS name and avatar support | ||
|
|
||
| ### 2. **Balance Overview** | ||
| - Native token balance display (ETH, AVAX, etc.) | ||
| - Real-time balance updates using wagmi hooks | ||
| - Network-specific balance information | ||
| - Token decimals and full balance details | ||
|
|
||
| ### 3. **Network Management** | ||
| - Visual network selector with supported chains: | ||
| - Sepolia Testnet (Ethereum) | ||
| - Avalanche Fuji Testnet | ||
| - One-click network switching | ||
| - Clear indication of active network | ||
| - Warning for unsupported networks | ||
|
|
||
| ### 4. **Wallet Information** | ||
| - ENS identity display with avatar | ||
| - Wallet type and address format verification | ||
| - Connection status indicators | ||
| - Security information about the connected wallet | ||
|
|
||
| ### 5. **Voting History** | ||
| - Placeholder for voting transaction history | ||
| - Ready for integration with blockchain voting records | ||
| - Statistics summary (total votes, elections participated, networks used) | ||
| - Transaction hash links to block explorers | ||
|
|
||
| ### 6. **Security Tips** | ||
| - Expandable security tips section | ||
| - Best practices for wallet security | ||
| - Warnings about phishing and scams | ||
| - Guidelines for safe Web3 interactions | ||
|
|
||
| ### 7. **User Experience** | ||
| - Beautiful gradient UI with Tailwind CSS | ||
| - Smooth animations using Framer Motion | ||
| - Responsive design (mobile, tablet, desktop) | ||
| - Toast notifications for user actions | ||
| - Loading states and skeleton screens | ||
|
|
||
| ## 🏗️ Architecture | ||
|
|
||
| ### File Structure | ||
| ``` | ||
| client/app/ | ||
| ├── wallet/ | ||
| │ └── page.tsx # Main wallet management page | ||
| └── components/ | ||
| └── Wallet/ | ||
| ├── WalletInfo.tsx # Wallet details and ENS info | ||
| ├── BalanceCard.tsx # Token balance display | ||
| ├── NetworkSelector.tsx # Network switching UI | ||
| ├── VotingHistory.tsx # Voting transaction history | ||
| └── SecurityTips.tsx # Security guidelines | ||
| ``` | ||
|
|
||
| ### Technology Stack | ||
| - **Next.js 14** - App Router | ||
| - **wagmi** - React Hooks for Ethereum | ||
| - **RainbowKit** - Wallet connection UI | ||
| - **viem** - Ethereum library | ||
| - **Framer Motion** - Animations | ||
| - **Heroicons** - Icons | ||
| - **Tailwind CSS** - Styling | ||
| - **react-hot-toast** - Notifications | ||
|
|
||
| ## 🎨 UI Components | ||
|
|
||
| ### WalletInfo | ||
| Displays detailed wallet information including: | ||
| - ENS avatar and name | ||
| - Wallet type and status | ||
| - Address format verification | ||
| - Security information | ||
|
|
||
| ### BalanceCard | ||
| Shows comprehensive balance information: | ||
| - Native token balance with 4 decimal precision | ||
| - Network-specific token symbols | ||
| - Gradient backgrounds based on network | ||
| - Full balance and decimals | ||
|
|
||
| ### NetworkSelector | ||
| Provides network switching functionality: | ||
| - Grid layout of supported networks | ||
| - Visual indication of active network | ||
| - One-click network switching | ||
| - Warning for unsupported networks | ||
|
|
||
| ### VotingHistory | ||
| Tracks user's voting participation: | ||
| - List of voting transactions | ||
| - Election names and timestamps | ||
| - Transaction hash links | ||
| - Statistics summary | ||
|
|
||
| ### SecurityTips | ||
| Educational component for security: | ||
| - Expandable accordion design | ||
| - Key security guidelines | ||
| - Warning about phishing | ||
| - Platform-specific safety notes | ||
|
|
||
| ## 🔗 Integration Points | ||
|
|
||
| ### wagmi Hooks Used | ||
| - `useAccount()` - Current wallet account info | ||
| - `useBalance()` - Token balance | ||
| - `useEnsName()` - ENS name resolution | ||
| - `useEnsAvatar()` - ENS avatar | ||
| - `useChainId()` - Current network ID | ||
| - `useSwitchChain()` - Network switching | ||
| - `useDisconnect()` - Wallet disconnection | ||
|
|
||
| ### RainbowKit Integration | ||
| - ConnectButton for wallet connection | ||
| - Automatic wallet provider detection | ||
| - Support for multiple wallet types | ||
|
|
||
| ## 🚀 Usage | ||
|
|
||
| ### Accessing the Wallet Page | ||
| 1. Navigate to `/wallet` route | ||
| 2. Or click "Wallet" in the navigation menu | ||
|
|
||
| ### Wallet Connection | ||
| If not connected: | ||
| 1. Click the "Connect Wallet" button | ||
| 2. Select your preferred wallet provider | ||
| 3. Approve the connection | ||
|
|
||
| If connected: | ||
| 1. View wallet details, balance, and history | ||
| 2. Switch networks as needed | ||
| 3. Disconnect when finished | ||
|
|
||
| ### Network Switching | ||
| 1. Scroll to the "Network Selection" section | ||
| 2. Click on the desired network card | ||
| 3. Approve the network switch in your wallet | ||
|
|
||
| ## 🔧 Future Enhancements | ||
|
|
||
| ### Planned Features | ||
| 1. **Voting History Integration** | ||
| - Fetch actual voting records from blockchain | ||
| - Filter by date, network, or election | ||
| - Export voting history | ||
|
|
||
| 2. **Multi-Wallet Support** | ||
| - Connect multiple wallets simultaneously | ||
| - Set default wallet for transactions | ||
| - Switch between connected wallets | ||
|
|
||
| 3. **Token Management** | ||
| - Display ERC-20 token balances | ||
| - Token transfer functionality | ||
| - Token approval management | ||
|
|
||
| 4. **Transaction History** | ||
| - Complete transaction history | ||
| - Filter and search capabilities | ||
| - CSV export functionality | ||
|
|
||
| 5. **Advanced Security** | ||
| - Wallet health checks | ||
| - Connection permissions audit | ||
| - Security score indicators | ||
|
|
||
| 6. **Analytics Dashboard** | ||
| - Voting participation metrics | ||
| - Network usage statistics | ||
| - Gas fee analytics | ||
|
|
||
| ## 📝 Code Examples | ||
|
|
||
| ### Using Wallet Info in Other Components | ||
| ```tsx | ||
| import { useAccount, useBalance } from 'wagmi'; | ||
|
|
||
| function MyComponent() { | ||
| const { address, isConnected } = useAccount(); | ||
| const { data: balance } = useBalance({ address }); | ||
|
|
||
| return ( | ||
| <div> | ||
| {isConnected && ( | ||
| <p>Balance: {balance?.formatted} {balance?.symbol}</p> | ||
| )} | ||
| </div> | ||
| ); | ||
| } | ||
| ``` | ||
|
|
||
| ### Network Switching | ||
| ```tsx | ||
| import { useSwitchChain } from 'wagmi'; | ||
| import { sepolia } from 'wagmi/chains'; | ||
|
|
||
| function SwitchNetwork() { | ||
| const { switchChain } = useSwitchChain(); | ||
|
|
||
| const handleSwitch = () => { | ||
| switchChain({ chainId: sepolia.id }); | ||
| }; | ||
|
|
||
| return <button onClick={handleSwitch}>Switch to Sepolia</button>; | ||
| } | ||
| ``` | ||
|
|
||
| ## 🐛 Known Issues | ||
|
|
||
| 1. **Voting History**: Currently uses mock data - needs integration with blockchain indexer or backend API | ||
| 2. **ENS Resolution**: May be slow on some networks - consider caching | ||
| 3. **Balance Updates**: Real-time updates depend on RPC endpoint reliability | ||
|
|
||
| ## 🤝 Contributing | ||
|
|
||
| When extending this feature: | ||
| 1. Follow the existing component structure | ||
| 2. Use wagmi hooks for blockchain interactions | ||
| 3. Maintain responsive design patterns | ||
| 4. Add loading states for async operations | ||
| 5. Include error handling with user-friendly messages | ||
|
|
||
| ## 📄 License | ||
|
|
||
| This feature is part of the Agora-Blockchain project and follows the same license. | ||
|
|
||
| ## 👥 Credits | ||
|
|
||
| Developed as part of the GSOC contribution to Agora-Blockchain. | ||
|
|
||
| --- | ||
|
|
||
| For more information, see the main project README or visit the [documentation](../README.md). |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,54 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "use client"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import React from "react"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import { motion } from "framer-motion"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface Category { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| title: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| icon: React.ComponentType<React.SVGProps<SVGSVGElement>>; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| color: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| description: string; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| interface CategoryCardProps { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| category: Category; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| index: number; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isSelected: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick: () => void; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| export default function CategoryCard({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| category, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| index, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isSelected, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }: CategoryCardProps) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const Icon = category.icon; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <motion.div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| initial={{ opacity: 0, y: 20 }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| animate={{ opacity: 1, y: 0 }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| transition={{ duration: 0.5, delay: index * 0.1 }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| whileHover={{ scale: 1.05 }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| whileTap={{ scale: 0.98 }} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| onClick={onClick} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`cursor-pointer rounded-xl p-6 shadow-md transition-all ${ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| isSelected | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? "bg-indigo-50 border-2 border-indigo-500" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : "bg-white border-2 border-transparent hover:shadow-lg" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <div | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| className={`inline-flex items-center justify-center w-12 h-12 rounded-lg mb-4 ${category.color}`} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <Icon className="h-6 w-6" /> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <h3 className="text-lg font-semibold text-gray-900 mb-2"> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| {category.title} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </h3> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| <p className="text-sm text-gray-600">{category.description}</p> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| </motion.div> | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+30
to
+52
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make the card keyboard-accessible. The card is a - <motion.div
+ <motion.button
+ type="button"
+ aria-pressed={isSelected}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: index * 0.1 }}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.98 }}
onClick={onClick}
- className={`cursor-pointer rounded-xl p-6 shadow-md transition-all ${
+ className={`w-full text-left cursor-pointer rounded-xl p-6 shadow-md transition-all focus:outline-none focus:ring-2 focus:ring-indigo-500 ${
isSelected
? "bg-indigo-50 border-2 border-indigo-500"
: "bg-white border-2 border-transparent hover:shadow-lg"
}`}
>
…
- </motion.div>
+ </motion.button>📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Prefer strict equality (
===) over loose equality (==).The early return placement correctly follows the Rules of Hooks by ensuring all hooks execute before any conditional returns. However, use strict equality for the undefined check.
Apply this diff:
📝 Committable suggestion
🤖 Prompt for AI Agents