mirror of
https://github.com/pezkuwichain/pwap.git
synced 2026-04-26 16:57:56 +00:00
Initial commit - PezkuwiChain Web Governance App
This commit is contained in:
@@ -0,0 +1,162 @@
|
||||
import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
|
||||
import { PEZKUWICHAIN_NETWORK, WALLET_ERRORS, initialWalletState, WalletState } from '@/lib/wallet';
|
||||
|
||||
interface WalletContextType extends WalletState {
|
||||
connectMetaMask: () => Promise<void>;
|
||||
connectWalletConnect: () => Promise<void>;
|
||||
disconnect: () => void;
|
||||
switchNetwork: () => Promise<void>;
|
||||
signTransaction: (tx: any) => Promise<string>;
|
||||
signMessage: (message: string) => Promise<string>;
|
||||
}
|
||||
|
||||
const WalletContext = createContext<WalletContextType | undefined>(undefined);
|
||||
|
||||
export const WalletProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||
const [walletState, setWalletState] = useState<WalletState>(initialWalletState);
|
||||
|
||||
const updateBalance = useCallback(async (address: string, provider: any) => {
|
||||
try {
|
||||
const balance = await provider.request({
|
||||
method: 'eth_getBalance',
|
||||
params: [address, 'latest']
|
||||
});
|
||||
setWalletState(prev => ({ ...prev, balance }));
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch balance:', error);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const connectMetaMask = useCallback(async () => {
|
||||
if (!window.ethereum) {
|
||||
setWalletState(prev => ({ ...prev, error: WALLET_ERRORS.NO_WALLET }));
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
|
||||
const chainId = await window.ethereum.request({ method: 'eth_chainId' });
|
||||
|
||||
setWalletState({
|
||||
isConnected: true,
|
||||
address: accounts[0],
|
||||
balance: '0',
|
||||
chainId,
|
||||
provider: window.ethereum,
|
||||
error: null
|
||||
});
|
||||
|
||||
await updateBalance(accounts[0], window.ethereum);
|
||||
} catch (error: any) {
|
||||
setWalletState(prev => ({
|
||||
...prev,
|
||||
error: error.code === 4001 ? WALLET_ERRORS.USER_REJECTED : WALLET_ERRORS.CONNECTION_FAILED
|
||||
}));
|
||||
}
|
||||
}, [updateBalance]);
|
||||
|
||||
const connectWalletConnect = useCallback(async () => {
|
||||
// WalletConnect implementation placeholder
|
||||
setWalletState(prev => ({
|
||||
...prev,
|
||||
error: 'WalletConnect integration coming soon'
|
||||
}));
|
||||
}, []);
|
||||
|
||||
const disconnect = useCallback(() => {
|
||||
setWalletState(initialWalletState);
|
||||
}, []);
|
||||
|
||||
const switchNetwork = useCallback(async () => {
|
||||
if (!walletState.provider) return;
|
||||
|
||||
try {
|
||||
await walletState.provider.request({
|
||||
method: 'wallet_switchEthereumChain',
|
||||
params: [{ chainId: PEZKUWICHAIN_NETWORK.chainId }]
|
||||
});
|
||||
} catch (error: any) {
|
||||
if (error.code === 4902) {
|
||||
try {
|
||||
await walletState.provider.request({
|
||||
method: 'wallet_addEthereumChain',
|
||||
params: [PEZKUWICHAIN_NETWORK]
|
||||
});
|
||||
} catch (addError) {
|
||||
setWalletState(prev => ({ ...prev, error: WALLET_ERRORS.NETWORK_ERROR }));
|
||||
}
|
||||
}
|
||||
}
|
||||
}, [walletState.provider]);
|
||||
|
||||
const signTransaction = useCallback(async (tx: any): Promise<string> => {
|
||||
if (!walletState.provider || !walletState.address) {
|
||||
throw new Error('Wallet not connected');
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await walletState.provider.request({
|
||||
method: 'eth_sendTransaction',
|
||||
params: [{ ...tx, from: walletState.address }]
|
||||
});
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || WALLET_ERRORS.TRANSACTION_FAILED);
|
||||
}
|
||||
}, [walletState.provider, walletState.address]);
|
||||
|
||||
const signMessage = useCallback(async (message: string): Promise<string> => {
|
||||
if (!walletState.provider || !walletState.address) {
|
||||
throw new Error('Wallet not connected');
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await walletState.provider.request({
|
||||
method: 'personal_sign',
|
||||
params: [message, walletState.address]
|
||||
});
|
||||
return result;
|
||||
} catch (error: any) {
|
||||
throw new Error(error.message || 'Failed to sign message');
|
||||
}
|
||||
}, [walletState.provider, walletState.address]);
|
||||
|
||||
useEffect(() => {
|
||||
if (window.ethereum) {
|
||||
window.ethereum.on('accountsChanged', (accounts: string[]) => {
|
||||
if (accounts.length === 0) {
|
||||
disconnect();
|
||||
} else {
|
||||
setWalletState(prev => ({ ...prev, address: accounts[0] }));
|
||||
updateBalance(accounts[0], window.ethereum);
|
||||
}
|
||||
});
|
||||
|
||||
window.ethereum.on('chainChanged', (chainId: string) => {
|
||||
setWalletState(prev => ({ ...prev, chainId }));
|
||||
});
|
||||
}
|
||||
}, [disconnect, updateBalance]);
|
||||
|
||||
return (
|
||||
<WalletContext.Provider value={{
|
||||
...walletState,
|
||||
connectMetaMask,
|
||||
connectWalletConnect,
|
||||
disconnect,
|
||||
switchNetwork,
|
||||
signTransaction,
|
||||
signMessage
|
||||
}}>
|
||||
{children}
|
||||
</WalletContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useWallet = () => {
|
||||
const context = useContext(WalletContext);
|
||||
if (!context) {
|
||||
throw new Error('useWallet must be used within WalletProvider');
|
||||
}
|
||||
return context;
|
||||
};
|
||||
Reference in New Issue
Block a user