🎯 Exemples recommandés
Balanced sample collections from various categories for you to explore
Intégration Frontend Web3
Exemples avancés d'intégration frontend Web3 incluant Ethers.js/Web3.js, support multi-chaînes, interactions de protocoles DeFi et interfaces marketplace NFT
💻 Intégration Avancée Ethers.js typescript
🟡 intermediate
⭐⭐⭐⭐
Frontend Web3 complet avec Ethers.js incluant interactions de contrat, écoute d'événements, estimation de gas, surveillance de transactions et gestion d'erreurs
⏱️ 40 min
🏷️ ethers, web3, frontend, dapp, blockchain
Prerequisites:
JavaScript, React, Ethereum basics, Web3 concepts
// Advanced Ethers.js Frontend Integration
// Complete Web3 DApp with Ethers.js v6
// Dependencies: ethers@^6.0.0, @walletconnect/web3-provider@^2.0.0
import { ethers } from 'ethers';
import { providers } from '@walletconnect/web3-provider';
import { watchContractEvent } from '@ethersproject/contracts';
import { Writable } from '@ethersproject/contracts';
// Contract ABIs (normally imported from JSON files)
const ERC20_ABI = [
// ... ERC-20 ABI
"function name() view returns (string)",
"function symbol() view returns (string)",
"function decimals() view returns (uint8)",
"function totalSupply() view returns (uint256)",
"function balanceOf(address) view returns (uint256)",
"function transfer(address, uint256) returns (bool)",
"function allowance(address, address) view returns (uint256)",
"function approve(address, uint256) returns (bool)",
"function transferFrom(address, address, uint256) returns (bool)",
"event Transfer(address indexed from, address indexed to, uint256 value)",
"event Approval(address indexed owner, address indexed spender, uint256 value)"
];
const NFT_MARKETPLACE_ABI = [
// NFT Marketplace ABI
"function listNFT(uint256, uint256) external",
"function buyNFT(uint256) external payable",
"function cancelListing(uint256) external",
"function updateListing(uint256, uint256) external",
"event NFTListed(uint256 indexed tokenId, uint256 price, address indexed seller)",
"event NFTSold(uint256 indexed tokenId, address indexed seller, address indexed buyer, uint256 price)",
"event ListingCancelled(uint256 indexed tokenId)"
];
interface Web3Config {
infuraProjectId?: string;
alchemyApiKey?: string;
defaultChainId: number;
supportedNetworks: NetworkConfig[];
rpcUrls: { [chainId: number]: string };
}
interface NetworkConfig {
chainId: number;
name: string;
rpcUrl: string;
blockExplorerUrl: string;
nativeCurrency: {
name: string;
symbol: string;
decimals: number;
};
}
class Web3Manager {
private provider: ethers.providers.Provider | null = null;
private signer: ethers.Signer | null = null;
private contracts: Map<string, ethers.Contract> = new Map();
private eventListeners: Map<string, ethers.Listener[]> = new Map();
private config: Web3Config;
private network: NetworkConfig | null = null;
private isWalletConnected: boolean = false;
constructor(config: Web3Config) {
this.config = config;
this.initializeProvider();
}
private initializeProvider() {
// Initialize with Infura fallback
const infuraUrl = this.config.infuraProjectId
? `https://mainnet.infura.io/v3/${this.config.infuraProjectId}`
: 'https://eth-mainnet.alchemyapi.io/v2/demo';
this.provider = new ethers.providers.JsonRpcProvider(infuraUrl);
console.log('🔗 Initialized with RPC provider');
}
// Wallet Connection Methods
async connectWallet(walletType: 'metamask' | 'walletconnect' = 'metamask') {
try {
let provider: ethers.providers.Web3Provider;
switch (walletType) {
case 'metamask':
provider = await this.connectMetaMask();
break;
case 'walletconnect':
provider = await this.connectWalletConnect();
break;
default:
throw new Error(`Unsupported wallet type: ${walletType}`);
}
this.provider = provider;
this.signer = provider.getSigner();
this.isWalletConnected = true;
// Get current network
const network = await provider.getNetwork();
this.network = this.config.supportedNetworks.find(
(config: NetworkConfig) => config.chainId === network.chainId
);
if (!this.network) {
throw new Error(`Network ${network.chainId} not supported`);
}
console.log('✅ Wallet connected:', {
network: network.name,
chainId: network.chainId,
account: await this.getConnectedAccount()
});
return true;
} catch (error) {
console.error('❌ Wallet connection failed:', error);
throw error;
}
}
private async connectMetaMask(): Promise<ethers.providers.Web3Provider> {
if (typeof window.ethereum === 'undefined') {
throw new Error('MetaMask is not installed');
}
// Request account access
await window.ethereum.request({ method: 'eth_requestAccounts' });
// Create provider
const provider = new ethers.providers.Web3Provider(window.ethereum);
// Listen for network changes
window.ethereum.on('chainChanged', () => {
this.handleNetworkChange();
});
// Listen for account changes
window.ethereum.on('accountsChanged', () => {
this.handleAccountChange();
});
return provider;
}
private async connectWalletConnect(): Promise<ethers.providers.Web3Provider> {
const wcProvider = new providers.Web3Provider({
infuraId: this.config.infuraProjectId
});
await wcProvider.enable();
return wcProvider;
}
async disconnectWallet() {
try {
this.provider = null;
this.signer = null;
this.isWalletConnected = false;
console.log('🔌 Wallet disconnected');
} catch (error) {
console.error('❌ Failed to disconnect wallet:', error);
}
}
private handleNetworkChange() {
console.log('⚡ Network changed, reloading...');
window.location.reload();
}
private handleAccountChange() {
console.log('👤 Account changed');
this.emit('accountChanged');
}
// Utility Methods
async getConnectedAccount(): Promise<string | null> {
if (!this.signer) return null;
return await this.signer.getAddress();
}
async getBalance(address?: string): Promise<string> {
const account = address || await this.getConnectedAccount();
if (!account) return '0';
const balance = await this.provider!.getBalance(account);
return ethers.utils.formatEther(balance);
}
async switchNetwork(chainId: number): Promise<void> {
try {
if (window.ethereum) {
await window.ethereum.request({
method: 'wallet_switchEthereumChain',
params: [{ chainId: `0x${chainId.toString(16)}` }]
});
} else {
throw new Error('Network switching not supported by current wallet');
}
} catch (error) {
console.error('❌ Network switch failed:', error);
throw error;
}
}
async addNetwork(networkConfig: NetworkConfig): Promise<void> {
try {
if (window.ethereum) {
await window.ethereum.request({
method: 'wallet_addEthereumChain',
params: [networkConfig]
});
} else {
throw new Error('Network addition not supported by current wallet');
}
} catch (error) {
console.error('❌ Failed to add network:', error);
throw error;
}
}
// Contract Interactions
getContract(address: string, abi: any[]): ethers.Contract {
const cacheKey = `${address}-${JSON.stringify(abi)}`;
if (this.contracts.has(cacheKey)) {
return this.contracts.get(cacheKey)!;
}
if (!this.signer) {
throw new Error('Wallet not connected');
}
const contract = new ethers.Contract(address, abi, this.signer);
this.contracts.set(cacheKey, contract);
return contract;
}
// ERC-20 Token Methods
async transferToken(tokenAddress: string, to: string, amount: string): Promise<ethers.TransactionResponse> {
try {
const contract = this.getContract(tokenAddress, ERC20_ABI);
const decimals = await contract.decimals();
const parsedAmount = ethers.utils.parseUnits(amount, decimals);
const tx = await contract.transfer(to, parsedAmount);
return await this.waitForTransaction(tx);
} catch (error) {
console.error('❌ Token transfer failed:', error);
throw error;
}
}
async getTokenInfo(tokenAddress: string) {
try {
const contract = this.getContract(tokenAddress, ERC20_ABI);
const [name, symbol, decimals, totalSupply] = await Promise.all([
contract.name(),
contract.symbol(),
contract.decimals(),
contract.totalSupply()
]);
return {
address: tokenAddress,
name,
symbol,
decimals: Number(decimals),
totalSupply: ethers.utils.formatEther(totalSupply)
};
} catch (error) {
console.error('❌ Failed to get token info:', error);
throw error;
}
}
async getTokenBalance(tokenAddress: string, userAddress?: string): Promise<string> {
try {
const contract = this.getContract(tokenAddress, ERC20_ABI);
const account = userAddress || await this.getConnectedAccount();
if (!account) return '0';
const balance = await contract.balanceOf(account);
const decimals = await contract.decimals();
return ethers.utils.formatUnits(balance, decimals);
} catch (error) {
console.error('❌ Failed to get token balance:', error);
throw error;
}
}
// NFT Marketplace Methods
async listNFT(marketplaceAddress: string, tokenId: string, price: string) {
try {
const contract = this.getContract(marketplaceAddress, NFT_MARKETPLACE_ABI);
const parsedPrice = ethers.utils.parseEther(price);
const tx = await contract.listNFT(tokenId, parsedPrice);
return await this.waitForTransaction(tx);
} catch (error) {
console.error('❌ NFT listing failed:', error);
throw error;
}
}
async buyNFT(marketplaceAddress: string, tokenId: string, maxPrice?: string) {
try {
const contract = this.getContract(marketplaceAddress, NFT_MARKETPLACE_ABI);
let tx: ethers.ContractTransaction;
if (maxPrice) {
const maxPriceWei = ethers.utils.parseEther(maxPrice);
tx = await contract.buyNFT(tokenId, {
value: maxPriceWei
});
} else {
tx = await contract.buyNFT(tokenId);
}
return await this.waitForTransaction(tx);
} catch (error) {
console.error('❌ NFT purchase failed:', error);
throw error;
}
}
// Transaction Management
async estimateGas(transaction: ethers.Transaction): Promise<string> {
try {
const gasEstimate = await this.provider!.estimateGas(transaction);
return gasEstimate.toString();
} catch (error) {
console.error('❌ Gas estimation failed:', error);
return '0';
}
}
async getTransactionReceipt(txHash: string) {
try {
return await this.provider!.getTransactionReceipt(txHash);
} catch (error) {
console.error('❌ Failed to get transaction receipt:', error);
throw error;
}
}
async waitForTransaction(
transaction: ethers.ContractTransaction,
confirmations: number = 1,
timeout: number = 30000
): Promise<ethers.TransactionResponse> {
try {
// Send transaction
const tx = await transaction.send();
// Wait for confirmation
const receipt = await tx.wait(confirmations);
// Emit transaction event
this.emit('transactionComplete', {
hash: receipt.hash,
status: receipt.status === 1 ? 'success' : 'failed',
gasUsed: receipt.gasUsed.toString(),
blockNumber: receipt.blockNumber.toString(),
timestamp: Date.now()
});
return receipt;
} catch (error) {
// Emit error event
this.emit('transactionError', {
error: error.message,
timestamp: Date.now()
});
throw error;
}
}
// Event Listening
listenToContractEvents(
contractAddress: string,
eventName: string,
callback: (event: any) => void
): () => void {
try {
const contract = this.getContract(contractAddress, []);
// Clean up existing listeners
this.removeAllListeners(contractAddress, eventName);
// Add new listener
const listener = (...args: any[]) => {
const event = contract.interface.parseLog(args[0], args[1], args[2]);
callback(event);
};
contract.on(eventName, listener);
// Store listener for cleanup
const listeners = this.eventListeners.get(contractAddress) || [];
listeners.push({ eventName, listener });
this.eventListeners.set(contractAddress, listeners);
return () => this.removeAllListeners(contractAddress, eventName);
} catch (error) {
console.error('❌ Failed to set up event listener:', error);
throw error;
}
}
private removeAllListeners(contractAddress: string, eventName?: string) {
const listeners = this.eventListeners.get(contractAddress);
if (!listeners) return;
const contract = this.contracts.get(`${contractAddress}-[]`);
if (!contract) return;
listeners.forEach(({ eventName: name, listener }) => {
if (!eventName || name === eventName) {
contract.removeAllListeners(name);
}
});
}
// Gas Optimization
async optimizeTransaction(transaction: ethers.Transaction): Promise<ethers.Transaction> {
try {
// Set reasonable gas limit if not provided
if (!transaction.gasLimit) {
const gasEstimate = await this.estimateGas(transaction);
transaction.gasLimit = Math.floor(Number(gasEstimate) * 1.2); // 20% buffer
}
// Set gas price if not provided
if (!transaction.gasPrice && this.network) {
const feeData = await this.provider!.getFeeData();
transaction.gasPrice = feeData.gasPrice;
}
// Set nonce if not provided
if (transaction.nonce === undefined) {
const nonce = await this.signer!.getTransactionCount();
transaction.nonce = nonce;
}
return transaction;
} catch (error) {
console.error('❌ Transaction optimization failed:', error);
return transaction;
}
}
// Batch Operations
async batchTransactions(transactions: ethers.Transaction[]): Promise<ethers.TransactionResponse[]> {
try {
// Process transactions in parallel with delays to avoid nonce conflicts
const results = await Promise.all(
transactions.map(async (tx, index) => {
// Add small delay between transactions
await new Promise(resolve => setTimeout(resolve, 100 * index));
return this.waitForTransaction(tx);
})
);
return results;
} catch (error) {
console.error('❌ Batch transactions failed:', error);
throw error;
}
}
// Event Emission
private listeners: Map<string, ((event: any) => void)[]> = new Map();
emit(eventName: string, data: any) {
const listeners = this.listeners.get(eventName) || [];
listeners.forEach(listener => listener(data));
}
on(eventName: string, listener: (event: any) => void) {
if (!this.listeners.has(eventName)) {
this.listeners.set(eventName, []);
}
this.listeners.get(eventName)!.push(listener);
}
off(eventName: string, listener: (event: any) => void) {
const listeners = this.listeners.get(eventName) || [];
const index = listeners.indexOf(listener);
if (index > -1) {
listeners.splice(index, 1);
}
}
// Multi-chain Support
async switchChain(newChainId: number) {
const targetNetwork = this.config.supportedNetworks.find(
(config: NetworkConfig) => config.chainId === newChainId
);
if (!targetNetwork) {
throw new Error(`Chain ${newChainId} not supported`);
}
try {
// Switch wallet to new chain
await this.switchNetwork(newChainId);
// Update provider
this.provider = new ethers.providers.JsonRpcProvider(targetNetwork.rpcUrl);
this.network = targetNetwork;
this.emit('chainChanged', {
chainId: newChainId,
network: targetNetwork.name
});
} catch (error) {
console.error('❌ Chain switch failed:', error);
throw error;
}
}
getCurrentNetwork(): NetworkConfig | null {
return this.network;
}
getNetworks(): NetworkConfig[] {
return this.config.supportedNetworks;
}
// Storage and Persistence
saveState() {
const state = {
isWalletConnected: this.isWalletConnected,
network: this.network,
connectedAccount: this.signer ? null : undefined
};
localStorage.setItem('web3-state', JSON.stringify(state));
}
loadState() {
try {
const saved = localStorage.getItem('web3-state');
if (saved) {
const state = JSON.parse(saved);
this.isWalletConnected = state.isWalletConnected || false;
this.network = state.network || null;
if (state.connectedAccount) {
this.reconnectAccount(state.connectedAccount);
}
}
} catch (error) {
console.warn('⚠️ Failed to load state:', error);
}
}
private async reconnectAccount(account: string) {
try {
if (this.provider && this.isWalletConnected) {
// Verify the account is still available
const availableAccounts = await this.provider.send('eth_requestAccounts', []);
if (availableAccounts.includes(account)) {
// Account is available, update signer
this.provider = new ethers.providers.Web3Provider(window.ethereum);
this.signer = this.provider.getSigner();
} else {
// Account no longer available, clear connection
this.isWalletConnected = false;
this.signer = null;
}
}
} catch (error) {
console.warn('⚠️ Failed to reconnect account:', error);
}
}
// DeFi Integration Examples
async swapTokens(
routerAddress: string,
tokenA: string,
tokenB: string,
amountIn: string,
amountOutMin: string,
slippage: number = 0.5
): Promise<ethers.TransactionResponse> {
try {
// Simplified Uniswap V2 Router example
const routerAbi = [
"function WETH() external view returns (address)",
"function swapExactTokensForTokens(uint256,uint256,address,bytes[])",
"function getAmountsOut(uint256,address[]) view returns (uint256[])",
"function swapExactETHForTokens(uint256,address[],uint256) external payable",
"function swapExactTokensForETH(address[],uint256,uint256) external"
];
const router = this.getContract(routerAddress, routerAbi);
// Calculate minimum output
const decimalsA = await this.getTokenDecimals(tokenA);
const decimalsB = await this.getTokenDecimals(tokenB);
const parsedAmountIn = ethers.utils.parseUnits(amountIn, decimalsA);
// This is a simplified example - actual implementation would require
// getting pool data and calculating proper amounts
const amountOut = await router.getAmountsOut(parsedAmountIn, [tokenA, tokenB]);
const minAmountOut = amountOut[1].mul(100 - slippage).div(100);
const tx = await router.swapExactTokensForTokens(
parsedAmountIn,
minAmountOut,
[tokenA, tokenB],
this.signer?.address()
);
return await this.waitForTransaction(tx);
} catch (error) {
console.error('❌ Token swap failed:', error);
throw error;
}
}
private async getTokenDecimals(tokenAddress: string): Promise<number> {
try {
const contract = this.getContract(tokenAddress, ERC20_ABI);
const decimals = await contract.decimals();
return Number(decimals);
} catch (error) {
return 18; // Default to 18 decimals for most tokens
}
}
// Liquidity Pool Management
async addLiquidity(
poolAddress: string,
tokenA: string,
tokenB: string,
amountA: string,
amountB: string,
slippage: number = 0.5
): Promise<ethers.TransactionResponse> {
try {
// Simplified liquidity pool example
const poolAbi = [
"function addLiquidity(uint256,uint256,address,address)",
"function removeLiquidity(uint256,uint256)",
"function getReserves() view returns (uint256,uint256)",
"event LiquidityAdded(address indexed provider, uint256 amountA, uint256 amountB)"
];
const pool = this.getContract(poolAddress, poolAbi);
const decimalsA = await this.getTokenDecimals(tokenA);
const decimalsB = await this.getTokenDecimals(tokenB);
const parsedAmountA = ethers.utils.parseUnits(amountA, decimalsA);
const parsedAmountB = ethers.utils.parseUnits(amountB, decimalsB);
const tx = await pool.addLiquidity(parsedAmountA, parsedAmountB, tokenA, tokenB);
return await this.waitForTransaction(tx);
} catch (error) {
console.error('❌ Add liquidity failed:', error);
throw error;
}
}
// Utility Methods
formatEther(wei: string): string {
try {
return ethers.utils.formatEther(wei);
} catch {
return wei;
}
}
parseEther(ether: string): ethers.BigNumber {
try {
return ethers.utils.parseEther(ether);
} catch {
return ethers.BigNumber(0);
}
}
formatUnits(value: ethers.BigNumber, decimals: number): string {
try {
return ethers.utils.formatUnits(value, decimals);
} catch {
return value.toString();
}
}
parseUnits(value: string, decimals: number): ethers.BigNumber {
try {
return ethers.utils.parseUnits(value, decimals);
} catch {
return ethers.BigNumber(0);
}
}
isValidAddress(address: string): boolean {
try {
return ethers.utils.isAddress(address);
} catch {
return false;
}
}
// Cleanup
destroy() {
// Remove all event listeners
this.eventListeners.forEach((listeners, contractAddress) => {
listeners.forEach(({ listener }) => {
this.off('eventChanged', listener);
});
});
// Clear references
this.providers = null;
this.signer = null;
this.contracts.clear();
this.eventListeners.clear();
}
}
// React Hook for Web3 Integration
// web3Hook.ts
import { useState, useEffect, useCallback } from 'react';
export const useWeb3 = () => {
const [web3Manager, setWeb3Manager] = useState<Web3Manager | null>(null);
const [isConnected, setIsConnected] = useState(false);
const [account, setAccount] = useState<string | null>(null);
const [network, setNetwork] = useState<any>(null);
const [balance, setBalance] = useState<string>('0');
// Initialize Web3Manager
useEffect(() => {
const config = {
infuraProjectId: process.env.NEXT_PUBLIC_INFURA_PROJECT_ID,
defaultChainId: 1,
supportedNetworks: [
{
chainId: 1,
name: 'Ethereum Mainnet',
rpcUrl: 'https://mainnet.infura.io/v3/YOUR_PROJECT_ID',
blockExplorerUrl: 'https://etherscan.io',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }
},
{
chainId: 137,
name: 'Polygon',
rpcUrl: 'https://polygon-rpc.com',
blockExplorerUrl: 'https://polygonscan.com',
nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 }
},
{
chainId: 56,
name: 'BSC',
rpcUrl: 'https://bsc-dataseid1.noderealapi.com',
blockExplorerUrl: 'https://bscscan.com',
nativeCurrency: { name: 'BNB', symbol: 'BNB', decimals: 18 }
}
]
};
const manager = new Web3Manager(config);
manager.loadState();
setWeb3Manager(manager);
setIsConnected(manager.isWalletConnected);
setNetwork(manager.getCurrentNetwork());
setAccount(await manager.getConnectedAccount());
// Save state on changes
manager.on('accountChanged', async () => {
setAccount(await manager.getConnectedAccount());
});
manager.on('chainChanged', (data) => {
setNetwork(data.network);
});
manager.on('balanceChanged', (data) => {
setBalance(data.balance);
});
// Cleanup on unmount
return () => {
manager.destroy();
};
}, []);
const connectWallet = useCallback(async (walletType: 'metamask' | 'walletconnect' = 'metamask') => {
if (!web3Manager) return;
try {
await web3Manager.connectWallet(walletType);
setIsConnected(true);
setAccount(await web3Manager.getConnectedAccount());
} catch (error) {
console.error('Failed to connect wallet:', error);
throw error;
}
}, [web3Manager]);
const disconnectWallet = useCallback(async () => {
if (!web3Manager) return;
try {
await web3Manager.disconnectWallet();
setIsConnected(false);
setAccount(null);
} catch (error) {
console.error('Failed to disconnect wallet:', error);
throw error;
}
}, [web3Manager]);
const switchNetwork = useCallback(async (chainId: number) => {
if (!web3Manager) return;
try {
await web3Manager.switchChain(chainId);
setNetwork(web3Manager.getCurrentNetwork());
} catch (error) {
console.error('Failed to switch network:', error);
throw error;
}
}, [web3Manager]);
const getContract = useCallback((address: string, abi: any[]) => {
return web3Manager?.getContract(address, abi);
}, [web3Manager]);
const transferToken = useCallback(async (tokenAddress: string, to: string, amount: string) => {
return web3Manager?.transferToken(tokenAddress, to, amount);
}, [web3Manager]);
const getTokenBalance = useCallback(async (tokenAddress: string) => {
return web3Manager?.getTokenBalance(tokenAddress);
}, [web3Manager]);
const buyNFT = useCallback(async (marketplaceAddress: string, tokenId: string, maxPrice?: string) => {
return web3Manager?.buyNFT(marketplaceAddress, tokenId, maxPrice);
}, [web3Manager]);
return {
web3Manager,
isConnected,
account,
network,
balance,
connectWallet,
disconnectWallet,
switchNetwork,
getContract,
transferToken,
getTokenBalance,
buyNFT
};
};
// Multi-chain Provider Manager
class MultiChainManager {
private providers: Map<number, ethers.providers.JsonRpcProvider> = new Map();
private wallets: Map<number, ethers.Wallet> = new Map();
private currentChainId: number = 1;
constructor(config: { [chainId: number]: string }) {
// Initialize providers for all supported chains
Object.entries(config).forEach(([chainId, rpcUrl]) => {
this.providers.set(Number(chainId), new ethers.providers.JsonRpcProvider(rpcUrl));
});
}
getProvider(chainId?: number): ethers.providers.JsonRpcProvider {
return this.providers.get(chainId || this.currentChainId);
}
switchChain(chainId: number): void {
this.currentChainId = chainId;
}
getCurrentChainId(): number {
return this.currentChainId;
}
async executeOnChain<T>(
chainId: number,
operation: (provider: ethers.providers.JsonRpcProvider) => Promise<T>
): Promise<T> {
const provider = this.getProvider(chainId);
return await operation(provider);
}
async executeOnAllChains<T>(
operation: (provider: ethers.providers.JsonRpcProvider, chainId: number) => Promise<T>
): Promise<Map<number, T>> {
const results = new Map<number, T>();
for (const [chainId, provider] of this.providers) {
try {
const result = await operation(provider, chainId);
results.set(chainId, result);
} catch (error) {
console.error(`Error on chain ${chainId}:`, error);
results.set(chainId, error);
}
}
return results;
}
}
export {
Web3Manager,
MultiChainManager,
useWeb3
};
// Usage example
// main.ts
async function main() {
console.log('🚀 Web3 Frontend Integration Demo');
// Initialize Web3 manager
const web3Manager = new Web3Manager({
infuraProjectId: process.env.INFURA_PROJECT_ID,
defaultChainId: 1,
supportedNetworks: [
{
chainId: 1,
name: 'Ethereum Mainnet',
rpcUrl: 'https://mainnet.infura.io/v3/YOUR_PROJECT_ID',
blockExplorerUrl: 'https://etherscan.io',
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 }
},
{
chainId: 137,
name: 'Polygon',
rpcUrl: 'https://polygon-rpc.com',
blockExplorerUrl: 'https://polygonscan.com',
nativeCurrency: { name: 'MATIC', symbol: 'MATIC', decimals: 18 }
}
]
});
try {
// Initialize and connect wallet
await web3Manager.initialize();
await web3Manager.connectWallet('metamask');
// Get wallet balance
const balance = await web3Manager.getBalance();
console.log(`💰 Wallet balance: ${balance} ETH`);
// Get token info
const tokenAddress = '0xA0b86a33E6D13A1F297Cd2B55E1A7B80A5C2C6EBD24A1C2A;
const tokenInfo = await web3Manager.getTokenInfo(tokenAddress);
console.log('📊 Token Info:', tokenInfo);
// Transfer tokens
if (parseFloat(balance) > 0.1) {
const recipient = '0x742d35Cc6634C0532925a3b8D4C9db96C4b4d8b6';
const amount = '0.01';
console.log(`💸 Transferring ${amount} tokens to ${recipient}...`);
const receipt = await web3Manager.transferToken(tokenAddress, recipient, amount);
console.log(`✅ Transfer complete: ${receipt.hash}`);
}
// Listen to contract events
const marketplaceAddress = '0x1234567890123456789012345678901234567890';
const stopListening = web3Manager.listenToContractEvents(
marketplaceAddress,
'NFTSold',
(event) => {
console.log(`🎨 NFT Sold! TokenId: ${event.tokenId}, Buyer: ${event.buyer}, Price: ${web3Manager.formatEther(event.price.toString())} ETH`);
}
);
// Listen for transaction events
web3Manager.on('transactionComplete', (event) => {
console.log(`✅ Transaction ${event.hash} ${event.status}`);
});
// Wait for some events
await new Promise(resolve => setTimeout(resolve, 10000));
stopListening();
} catch (error) {
console.error('❌ Demo failed:', error);
}
}
if (require.main === module) {
main();
}