image

2017 Schedule Confirmed

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mattis maximus felis et consequat. Proin sodales magna non nibh consectetur ullamcorper. Nunc luctus malesuada cursus. Quisque vehicula est libero, et aliquet ex porttitor eget. Vivamus vehicula tristique lectus, non consequat nibh blandit vel. Praesent pellentesque ut ante nec venenatis. Maecenas vitae dui id leo ultrices tempus in eget mi. Duis neque tellus, convallis et imperdiet iaculis, feugiat vitae libero. In ligula sapien, tincidunt eu libero , aliquam a vulputate nunc. Quisque ultricies ante neque, non facilisis eros eleifend non. Sed sit amet ante diam. Donec ante nec enim convallis sollicitudin. Praesent turpis magna, sollicitudin vel ipsum at, cursus venenatis augue.

Mauris a interdum odio. Sed ac mi lacus. Mauris sed nulla suscipit, cursus mauris sed, porttitor ante. Cras nisi urna, molestie non lobortis ac, tempus non lectus. Sed vitae vehicula quam. In hac habitasse platea dictumst. Integer tempus et lectus eu dignissim. Cras fermentum augue a felis scelerisque condimentum. Maecenas commodo placerat fermentum. Donec faucibus porttitor ligula in semper. Ut imperdiet sed nisi eu maximus. Sed dolor lacus, eleifend vitae cursus luctus, varius vel mauris. Sed placerat quam ex, id fermentum dolor molestie sed. Donec consectetur tortor quam, at malesuada urna iaculis malesuada.

Leave a comment

PNFPB Install PWA using share icon

For IOS and IPAD browsers, Install PWA using add to home screen in ios safari browser or add to dock option in macos safari browser

// 2. Initialize WalletConnectModal with your project ID // 3. Use modal.openModal() for QR code display // 4. Handle connection events with modal.subscribeModal() // // Current implementation provides wallet selection UI and installation guidance // without requiring external dependencies. (function() { 'use strict'; console.log('[RIZE WalletConnect] Enhanced v9.0 initializing...'); console.log('[RIZE WalletConnect] Project ID:', 'b742124c82f12ab6be54fe5c46b3f991'); console.log('[RIZE WalletConnect] Analytics:', false); console.log('[RIZE WalletConnect] Debug Mode:', false); // Configuration const CONFIG = { projectId: 'b742124c82f12ab6be54fe5c46b3f991', explorerApi: 'https://explorer-api.walletconnect.com', sdkType: 'wcm', sdkVersion: 'js-2.6.2', analytics: false, cacheExpiry: 3600 * 1000, debugMode: true, // Force debug mode for troubleshooting token: { contract: '2uWZLXzbbtmPbJVZjMpm17CPnfL73RFrfvHntsKYpump', symbol: 'RIZE', decimals: 6 } }; // Enhanced WalletConnect namespace const RizeWalletConnect = { isModalOpen: false, isInitialized: false, connectedAddress: null, isTokenPage: false, currentFilter: 'all', walletListings: { all: [], recommended: [], installed: [], recent: [] }, cache: { data: null, timestamp: null, version: 'v9.0' }, imageObserver: null, connectionRetries: new Map(), // Initialize the plugin init: function() { if (this.isInitialized) { this.log('Already initialized, skipping...'); return; } this.isInitialized = true; this.log('Initializing enhanced v9.0...'); // Setup intersection observer for lazy loading this.setupImageObserver(); // Load cached data this.loadCache(); if (this.isTokenPage) { this.initTokenPage(); } else { this.addWalletButton(); // Retry after DOM mutations setTimeout(() => this.addWalletButton(), 2000); } // Setup performance monitoring this.setupPerformanceMonitoring(); }, // Enhanced logging log: function(...args) { if (CONFIG.debugMode) { console.log('[RIZE WalletConnect]', ...args); } }, // Performance monitoring setupPerformanceMonitoring: function() { if (CONFIG.analytics) { // Monitor connection time this.performanceMarkers = new Map(); } }, // Mark performance event markPerformance: function(eventName) { if (CONFIG.analytics) { this.performanceMarkers.set(eventName, performance.now()); } }, // Measure performance between marks measurePerformance: function(startEvent, endEvent) { if (CONFIG.analytics && this.performanceMarkers.has(startEvent)) { const duration = performance.now() - this.performanceMarkers.get(startEvent); this.trackEvent('performance', { metric: `${startEvent}_to_${endEvent}`, duration: Math.round(duration) }); return duration; } return 0; }, // Setup intersection observer for lazy loading setupImageObserver: function() { if ('IntersectionObserver' in window) { this.imageObserver = new IntersectionObserver((entries) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; const src = img.dataset.src; if (src && !img.src) { // Preload image const tempImg = new Image(); tempImg.onload = () => { img.src = src; img.classList.add('loaded'); // Hide fallback const fallback = img.parentElement.querySelector('.wc-wallet-icon-fallback'); if (fallback) { fallback.style.display = 'none'; } }; tempImg.onerror = () => { this.log('Failed to load image:', src); // Keep fallback visible }; tempImg.src = src; } this.imageObserver.unobserve(img); } }); }, { rootMargin: '50px' }); } }, // Load cache loadCache: function() { try { const cached = localStorage.getItem('rize_wallet_cache'); if (cached) { const parsed = JSON.parse(cached); if (parsed.version === this.cache.version && Date.now() - parsed.timestamp < CONFIG.cacheExpiry) { this.cache = parsed; this.log('Loaded wallet cache:', parsed.data.length, 'wallets'); } } } catch (e) { this.log('Failed to load cache:', e); } }, // Save cache saveCache: function(data) { try { this.cache = { data: data, timestamp: Date.now(), version: this.cache.version }; localStorage.setItem('rize_wallet_cache', JSON.stringify(this.cache)); } catch (e) { this.log('Failed to save cache:', e); } }, // Enhanced notification system showNotification: function(message, type = 'info', duration = 5000) { // Create notification container if it doesn't exist let notificationGroup = document.querySelector('.rize-notification-group'); if (!notificationGroup) { notificationGroup = document.createElement('div'); notificationGroup.className = 'rize-notification-group'; document.body.appendChild(notificationGroup); } // Create notification const notification = document.createElement('div'); notification.className = `rize-notification ${type}`; // Add icon based on type const icon = document.createElement('span'); icon.innerHTML = this.getNotificationIcon(type); const text = document.createElement('span'); text.textContent = message; notification.appendChild(icon); notification.appendChild(text); // Add to group notificationGroup.appendChild(notification); // Auto remove setTimeout(() => { notification.style.animation = 'slideInRight 0.3s ease-out reverse'; setTimeout(() => { notification.remove(); if (notificationGroup.children.length === 0) { notificationGroup.remove(); } }, 300); }, duration); }, // Get notification icon getNotificationIcon: function(type) { const icons = { success: '', error: '', warning: '', info: '' }; return icons[type] || icons.info; }, // Enhanced wallet fetching with caching fetchWalletListings: async function() { // Return cache if valid if (this.cache.data) { this.log('Using cached wallet data'); return this.cache.data; } this.markPerformance('fetch_wallets_start'); // If no project ID, use static list immediately if (!CONFIG.projectId || CONFIG.projectId.length < 32) { this.log('No valid project ID, using static wallet list'); const staticList = this.getStaticWalletList(); const result = { all: staticList, recommended: staticList.slice(0, 12) }; this.saveCache(result); return result; } try { const isMobile = this.isMobile(); const endpoint = isMobile ? '/w3m/v1/getMobileListings' : '/w3m/v1/getDesktopListings'; const params = new URLSearchParams({ projectId: CONFIG.projectId, sdkType: CONFIG.sdkType, sdkVersion: CONFIG.sdkVersion, page: '1', entries: '100', // Increased for better coverage version: '2' }); const response = await fetch(`${CONFIG.explorerApi}${endpoint}?${params}`); if (!response.ok) { throw new Error('Failed to fetch wallet listings'); } const data = await response.json(); const wallets = Object.values(data.listings || {}); // Transform wallet data with full metadata const transformedWallets = wallets.map((wallet, index) => ({ ...wallet, id: wallet.id, name: wallet.name, image_id: wallet.image_id || wallet.image_url?.sm?.split('/').pop()?.split('?')[0], popularity: wallets.length - index, // Higher index = more popular homepage: wallet.homepage, mobile: wallet.mobile, desktop: wallet.desktop, webapp: wallet.webapp, injected: wallet.injected, users: wallet.recent || 0 })); // Fetch recommended wallets const recommendedParams = new URLSearchParams({ projectId: CONFIG.projectId, sdkType: CONFIG.sdkType, sdkVersion: CONFIG.sdkVersion, page: '1', entries: '12', version: '2' }); const recommendedResponse = await fetch(`${CONFIG.explorerApi}${endpoint}?${recommendedParams}`); const recommendedData = await recommendedResponse.json(); const recommendedWallets = Object.values(recommendedData.listings || {}); const result = { all: transformedWallets, recommended: recommendedWallets.slice(0, 12) }; // Save to cache this.saveCache(result); this.measurePerformance('fetch_wallets_start', 'fetch_wallets_end'); return result; } catch (error) { this.log('Failed to fetch wallet listings:', error); // Return static list as fallback with proper structure const staticList = this.getStaticWalletList(); const result = { all: staticList, recommended: staticList.slice(0, 12) }; this.saveCache(result); return result; } }, // Get static wallet list with enhanced metadata and icons getStaticWalletList: function() { return [ { id: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96', name: 'MetaMask', image_id: '5195e9db-94d8-4579-6f11-ef553be95100', users: 21500000, homepage: 'https://metamask.io/download/', mobile: { native: 'metamask://', universal: 'https://metamask.app.link' }, desktop: { native: 'metamask://', universal: null }, injected: [{ namespace: 'eip155', injected_id: 'isMetaMask' }], icon: 'data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDIyLjAuMSwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zOmV2PSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL3htbC1ldmVudHMiCgkgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgeD0iMHB4IiB5PSIwcHgiIHZpZXdCb3g9IjAgMCAzMTguNiAzMTguNiIKCSBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCAzMTguNiAzMTguNjsiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLnN0MHtmaWxsOiNFMjc2MUM7c3Ryb2tlOiNFMjc2MUM7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30KCS5zdDF7ZmlsbDojRTQ3NjFCO3N0cm9rZTojRTQ3NjFCO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9Cgkuc3Qye2ZpbGw6I0Q3QzFCMztzdHJva2U6I0Q3QzFCMztzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7fQoJLnN0M3tmaWxsOiMyMzM0NDc7c3Ryb2tlOiMyMzM0NDc7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30KCS5zdDR7ZmlsbDojQ0Q2MTE2O3N0cm9rZTojQ0Q2MTE2O3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9Cgkuc3Q1e2ZpbGw6I0U0NzUxRjtzdHJva2U6I0U0NzUxRjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7fQoJLnN0NntmaWxsOiNGNjg1MUY7c3Ryb2tlOiNGNjg1MUY7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30KCS5zdDd7ZmlsbDojQzBBRDlFO3N0cm9rZTojQzBBRDlFO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDt9Cgkuc3Q4e2ZpbGw6IzE2MTYxNjtzdHJva2U6IzE2MTYxNjtzdHJva2UtbGluZWNhcDpyb3VuZDtzdHJva2UtbGluZWpvaW46cm91bmQ7fQoJLnN0OXtmaWxsOiM3NjNEMTY7c3Ryb2tlOiM3NjNEMTY7c3Ryb2tlLWxpbmVjYXA6cm91bmQ7c3Ryb2tlLWxpbmVqb2luOnJvdW5kO30KPC9zdHlsZT4KPHBvbHlnb24gY2xhc3M9InN0MCIgcG9pbnRzPSIyNzQuMSw2MS40IDMwMC4xLDIxNS41IDI0Ny40LDI4NS4zIDI3NC4xLDYxLjQgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iNDQuNCw2MS40IDE4LDIxMy45IDcxLjEsMjg1LjMgNDQuNCw2MS40ICIvPgo8cG9seWdvbiBjbGFzcz0ic3QyIiBwb2ludHM9IjIzOC4zLDIwNi4yIDIxMS44LDI0Ny40IDI2OC41LDI2My43IDI4NC44LDIwNy43IDIzOC4zLDIwNi4yICIvPgo8cG9seWdvbiBjbGFzcz0ic3QyIiBwb2ludHM9IjMzLjksIDIwNy43IDUwLjEsMjYzLjcgMTA2LjgsMjQ3LjQgODAuMywyMDYuMiAzMy45LDIwNy43ICIvPgo8cG9seWdvbiBjbGFzcz0ic3QyIiBwb2ludHM9IjEwMy42LDEzOC4yIDg3LjgsMTYyLjEgMTQ0LjEsMTY0LjYgMTQyLjEsMTA0LjEgMTAzLjYsMTM4LjIgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDIiIHBvaW50cz0iMjE0LjksMTM4LjIgMTc1LjksMTAzLjQgMTc0LjYsMTY0LjYgMjMwLjgsMTYyLjEgMjE0LjksMTM4LjIgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDIiIHBvaW50cz0iMTA2LjgsMjQ3LjQgMTQwLjYsMjMwLjkgMTExLjQsMjA4LjEgMTA2LjgsMjQ3LjQgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDIiIHBvaW50cz0iMTc3LjksMjMwLjkgMjExLjgsMjQ3LjQgMjA3LjEsMjA4LjEgMTc3LjksMjMwLjkgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDMiIHBvaW50cz0iMjExLjgsMjQ3LjQgMTc3LjksMjMwLjkgMTgwLjYsMjUzIDE4MC4zLDI2Mi4zIDIxMS44LDI0Ny40ICIvPgo8cG9seWdvbiBjbGFzcz0ic3QzIiBwb2ludHM9IjEwNi44LDI0Ny40IDEzOC4zLDI2Mi4zIDEzOCwyNTMgMTQwLjYsMjMwLjkgMTA2LjgsMjQ3LjQgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDQiIHBvaW50cz0iMTM4LjgsMTkzLjUgMTEwLjYsMTg1LjIgMTMwLjUsMTc2LjEgMTM4LjgsMTkzLjUgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDQiIHBvaW50cz0iMTc5LjcsMTkzLjUgMTg4LDE3Ni4xIDIwOCwxODUuMiAxNzkuNywxOTMuNSAiLz4KPHBvbHlnb24gY2xhc3M9InN0NSIgcG9pbnRzPSIxMDYuOCwyNDcuNCAxMTEuNiwyMDYuOCA4MC4zLDIwNi4yIDEwNi44LDI0Ny40ICIvPgo8cG9seWdvbiBjbGFzcz0ic3Q1IiBwb2ludHM9IjIwNy4xLDIwNi44IDIxMS44LDI0Ny40IDIzOC4zLDIwNi4yIDIwNy4xLDIwNi44ICIvPgo8cG9seWdvbiBjbGFzcz0ic3Q1IiBwb2ludHM9IjIzMC44LDE2Mi4xIDE3NC42LDE2NC42IDE3OS44LDE5My41IDIwOCwxODUuMiAyMzAuOCwxNjIuMSAiLz4KPHBvbHlnb24gY2xhc3M9InN0NSIgcG9pbnRzPSIxMTAuNiwxODUuMiAxMzguOCwxOTMuNSAxNDQuMSwxNjQuNiA4Ny44LDE2Mi4xIDExMC42LDE4NS4yICIvPgo8cG9seWdvbiBjbGFzcz0ic3Q2IiBwb2ludHM9Ijg3LjgsMTYyLjEgMTExLjQsMjA4LjEgMTEwLjYsMTg1LjIgODcuOCwxNjIuMSAiLz4KPHBvbHlnb24gY2xhc3M9InN0NiIgcG9pbnRzPSIyMDgsMTg1LjIgMjA3LjEsMjA4LjEgMjMwLjgsMTYyLjEgMjA4LDE4NS4yICIvPgo8cG9seWdvbiBjbGFzcz0ic3Q2IiBwb2ludHM9IjE0NC4xLDE2NC42IDEzOC44LDE5My41IDE0NS40LDIyNy42IDE0Ni45LDE4Mi44IDE0NC4xLDE2NC42ICIvPgo8cG9seWdvbiBjbGFzcz0ic3Q2IiBwb2ludHM9IjE3NC42LDE2NC42IDE3MS45LDE4Mi44IDE3My4xLDIyNy42IDE3OS44LDE5My41IDE3NC42LDE2NC42ICIvPgo8cG9seWdvbiBjbGFzcz0ic3Q3IiBwb2ludHM9IjE3OS44LDE5My41IDE3My4xLDIyNy42IDE3Ny45LDIzMC45IDE4MC42LDI1MyAyMDcuMSwyMDguMSAyMDgsMTg1LjIgMTc5LjgsMTkzLjUgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDciIHBvaW50cz0iMTEwLjYsMTg1LjIgMTExLjQsMjA4LjEgMTM4LDI1MyAxNDAuNiwyMzAuOSAxNDUuNCwyMjcuNiAxMzguOCwxOTMuNSAxMTAuNiwxODUuMiAiLz4KPHBvbHlnb24gY2xhc3M9InN0OCIgcG9pbnRzPSIxODAuMywgMjYyLjMgMTgwLjYsMjUzIDE3Ny45LDIzMC45IDE0MC42LDIzMC45IDEzOCwyNTMgMTM4LjMsMjYyLjMgMTgwLjMsMjYyLjMgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDkiIHBvaW50cz0iMTQyLjEsMTA0LjEgMTQ0LjEsMTY0LjYgMjMwLjgsMTYyLjEgMjE0LjksMTM4LjIgMTQyLjEsMTA0LjEgIi8+Cjxwb2x5Z29uIGNsYXNzPSJzdDkiIHBvaW50cz0iMTAzLjYsMTM4LjIgODcuOCwxNjIuMSAxNzQuNiwxNjQuNiAxNzUuOSwxMDMuNCAxMDMuNiwxMzguMiAiLz4KPC9zdmc+' }, { id: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0', name: 'Trust Wallet', image_id: '0528ee7e-16d1-4089-21e3-bbfb41933100', users: 7000000, homepage: 'https://trustwallet.com/download', mobile: { native: 'trust://', universal: 'https://link.trustwallet.com' }, desktop: { native: null, universal: null }, icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMyIDY0QzQ5LjY3MzEgNjQgNjQgNDkuNjczMSA2NCAzMkM2NCAxNC4zMjY5IDQ5LjY3MzEgMCAzMiAwQzE0LjMyNjkgMCAwIDE0LjMyNjkgMCAzMkMwIDQ5LjY3MzEgMTQuMzI2OSA2NCAzMiA2NFoiIGZpbGw9IiMzMzc1QkIiLz4KPHBhdGggZD0iTTMxLjU1MiAxOC4wNDhDMzcuODg4IDE4LjA0OCA0My4wMDggMjMuMTY4IDQzLjAwOCAyOS41MDRDNDMuMDA4IDI5LjY5NiA0My4wMDggMjkuODg4IDQzLjAwOCAzMC4wOEM0MyAzNC44IDQxLjA3MiAzOS4wODggMzcuODg4IDQyLjI3MkMzNy43NiA0Mi40IDM3LjU2OCA0Mi40NzIgMzcuMzc2IDQyLjQ3MkgzMS41NTJDMzEuMzYgNDIuNDcyIDMxLjE2OCA0Mi40IDMxLjA0IDQyLjI3MkMyNy44NTYgMzkuMDg4IDI1LjkyOCAzNC44IDI1LjkyIDMwLjA4QzI1LjkyIDI5Ljg4OCAyNS45MiAyOS42OTYgMjUuOTIgMjkuNTA0QzI1LjkyIDIzLjE2OCAzMS4wNDggMTguMDQ4IDMxLjU1MiAxOC4wNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=' }, { id: 'fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa', name: 'Coinbase Wallet', image_id: '2c921904-3522-415d-7ad7-16cf88c8f489', users: 4500000, homepage: 'https://www.coinbase.com/wallet', mobile: { native: 'cbwallet://', universal: 'https://go.cb-w.com' }, desktop: { native: 'cbwallet://', universal: null }, injected: [{ namespace: 'eip155', injected_id: 'isCoinbaseWallet' }], icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE2IDBBIDE2IDE2IDAgMSAwIDE2IDMyQTE2IDE2IDAgMSAwIDE2IDBaIiBmaWxsPSIjMTY1MkYwIi8+CjxwYXRoIGQ9Ik0xNiA3QzExLjAyOTQgNyA3IDExLjAyOTQgNyAxNkM3IDIwLjk3MDYgMTEuMDI5NCAyNSAxNiAyNUMyMC45NzA2IDI1IDI1IDIwLjk3MDYgMjUgMTZDMjUgMTEuMDI5NCAyMC45NzA2IDcgMTYgN1pNMTkuNSAxN0gxNFYxNUgxOS41VjE3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+' }, { id: '1ae92b26df02f0abca6304df07debccd18262fdf5fe82daa81593582dac9a369', name: 'Rainbow', image_id: '3e89b39e-198a-4ab9-244e-ab01bb52b000', users: 1200000, homepage: 'https://rainbow.me', mobile: { native: 'rainbow://', universal: 'https://rnbwapp.com' }, desktop: { native: null, universal: null } }, { id: '3d2e24350fd2fa019ab8e39170e2eb94e1ae07ed54b982e94bca24f8b8e192a8', name: 'Binance Web3 Wallet', image_id: '7f165680-b020-46d5-f57b-e8d23b9ace00', users: 3500000, homepage: 'https://www.binance.com/en/web3wallet', mobile: { native: 'bnc://', universal: 'https://app.binance.com' }, desktop: { native: null, universal: null } }, { id: '0b415a746fb9ee99cce155c2ceca0c6f6061b1dbca2d722b3ba16381d0562150', name: 'SafePal', image_id: '0b415a74-40c7-4d1e-b7c8-c14e5c96d400', users: 800000, homepage: 'https://www.safepal.com/download', mobile: { native: 'safepalwallet://', universal: null }, desktop: { native: null, universal: null } }, { id: '20459438007b75f4f4acb98bf29aa3b800550309646d375da5fd4aac6c2a2c66', name: 'TokenPocket', image_id: 'f5b4eeb7-5212-4c38-bd26-464e2e8f9e00', users: 1000000, homepage: 'https://www.tokenpocket.pro/en/download/app', mobile: { native: 'tpoutside://', universal: null }, desktop: { native: null, universal: null } }, { id: '19177a98252e07ddfc9af2083ba8e07ef627cb6103467ffebb3f8f4205fd7927', name: 'Ledger Live', image_id: '2e0411fd-623b-4156-88c6-3fb0bfb04d00', users: 500000, homepage: 'https://www.ledger.com/ledger-live', mobile: { native: 'ledgerlive://', universal: null }, desktop: { native: 'ledgerlive://', universal: null } }, { id: 'ecc4036f814562b41a5268adc86270fba1365471402006302e70169465b7ac18', name: 'Zerion', image_id: 'bc949c5d-2d7b-4c3e-b153-dd9a06b1a00', users: 300000, homepage: 'https://zerion.io/download', mobile: { native: 'zerion://', universal: 'https://wallet.zerion.io' }, desktop: { native: null, universal: null }, webapp: { universal: 'https://app.zerion.io' } }, { id: '7674bb4e353bf52886768a3ddc2a4562ce2f4191c80831291218ebd90f5f5e26', name: 'MathWallet', image_id: '7674bb4e-3c96-46ad-8319-b33131c70c00', users: 600000, homepage: 'https://mathwallet.org', mobile: { native: 'mathwallet://', universal: null }, desktop: { native: null, universal: null } }, { id: 'ef333840793884b4e57e2dd2e23a4dc014ba3cd3eabbe6bdec8f08e6d6f421f7', name: 'imToken', image_id: 'ef333408-c20f-4909-8d69-e066a2e7a600', users: 1200000, homepage: 'https://token.im/download', mobile: { native: 'imtokenv2://', universal: null }, desktop: { native: null, universal: null } }, { id: '6193353e17504afc4bb982ee743ab970cd5cf842a35ecc9b7de61c150cf291e0', name: 'Keplr', image_id: 'e65d56fb-dd92-4636-3147-011716817800', users: 400000, homepage: 'https://www.keplr.app/download', mobile: { native: 'keplrwallet://', universal: null }, desktop: { native: null, universal: null }, injected: [{ namespace: 'eip155', injected_id: 'isKeplr' }] } ]; }, // Get wallet image URL with fallback getWalletImageUrl: function(wallet) { // If wallet has a direct icon, use it if (wallet.icon) { return wallet.icon; } if (!CONFIG.projectId || CONFIG.projectId.length < 32) { this.log('No valid project ID for fetching wallet images'); return null; } // Use image_id if available if (wallet.image_id) { return `${CONFIG.explorerApi}/w3m/v1/getWalletImage/${wallet.image_id}?projectId=${CONFIG.projectId}&sdkType=${CONFIG.sdkType}&sdkVersion=${CONFIG.sdkVersion}`; } // Fallback to image_url if (wallet.image_url) { return wallet.image_url.sm || wallet.image_url.md || wallet.image_url.lg; } // Last resort: use wallet ID if (wallet.id) { return `${CONFIG.explorerApi}/w3m/v1/getWalletImage/${wallet.id}?projectId=${CONFIG.projectId}&sdkType=${CONFIG.sdkType}&sdkVersion=${CONFIG.sdkVersion}`; } return null; }, // Create enhanced modal with status indicator createModal: function() { const modal = document.createElement('div'); modal.className = 'rize-wallet-modal'; modal.innerHTML = `

WalletConnect

Ready to connect
`; return modal; }, // Enhanced wallet selection modal showWalletSelection: async function(detectedWallets, button, callback) { this.log('Showing enhanced wallet selection modal'); if (this.isModalOpen) { this.log('Modal already open, skipping'); return; } this.markPerformance('modal_open_start'); // Remove any existing modals document.querySelectorAll('.rize-wallet-modal-overlay').forEach(el => el.remove()); this.isModalOpen = true; // Create overlay const overlay = document.createElement('div'); overlay.className = 'rize-wallet-modal-overlay'; // Create modal const modal = this.createModal(); overlay.appendChild(modal); // Add to DOM document.body.appendChild(overlay); // Get elements const closeBtn = modal.querySelector('.wc-modal-close'); const searchInput = modal.querySelector('.wc-search-input'); const searchClear = modal.querySelector('.wc-search-clear'); const filterTabs = modal.querySelectorAll('.wc-filter-tab'); const walletGrid = modal.querySelector('.wc-wallet-grid'); const categoriesContainer = modal.querySelector('.wc-wallet-categories'); // Track modal open this.trackEvent('modal_opened', { detected_wallets: detectedWallets.length }); // Show loading state const showLoading = () => { walletGrid.innerHTML = `
${[...Array(8)].map((_, i) => `
`).join('')}
`; categoriesContainer.innerHTML = ''; }; // Show loading initially showLoading(); // Close modal function const closeModal = () => { overlay.style.animation = 'wc-fadeOut 0.2s ease-out'; modal.style.animation = 'wc-slideDown 0.3s cubic-bezier(0.16, 1, 0.3, 1)'; setTimeout(() => { overlay.remove(); this.isModalOpen = false; if (button) { this.resetButton(button, 'Connect Wallet'); } }, 200); this.trackEvent('modal_closed'); }; // Event handlers closeBtn.addEventListener('click', closeModal); overlay.addEventListener('click', (e) => { if (e.target === overlay) { closeModal(); } }); // Escape key handler const escapeHandler = (e) => { if (e.key === 'Escape' && this.isModalOpen) { closeModal(); document.removeEventListener('keydown', escapeHandler); } }; document.addEventListener('keydown', escapeHandler); // Keyboard navigation const setupKeyboardNavigation = () => { const walletItems = modal.querySelectorAll('.wc-wallet-item'); let focusIndex = -1; modal.addEventListener('keydown', (e) => { const itemsPerRow = window.innerWidth <= 480 ? 3 : 4; switch(e.key) { case 'ArrowDown': e.preventDefault(); focusIndex = Math.min(focusIndex + itemsPerRow, walletItems.length - 1); break; case 'ArrowUp': e.preventDefault(); focusIndex = Math.max(focusIndex - itemsPerRow, 0); break; case 'ArrowLeft': e.preventDefault(); focusIndex = Math.max(focusIndex - 1, 0); break; case 'ArrowRight': e.preventDefault(); focusIndex = Math.min(focusIndex + 1, walletItems.length - 1); break; case 'Enter': if (focusIndex >= 0 && walletItems[focusIndex]) { walletItems[focusIndex].click(); } break; } if (focusIndex >= 0 && walletItems[focusIndex]) { walletItems[focusIndex].focus(); } }); }; // Search functionality const setupSearch = () => { let searchTimeout; searchInput.addEventListener('input', (e) => { const hasValue = e.target.value.length > 0; searchClear.style.display = hasValue ? 'block' : 'none'; clearTimeout(searchTimeout); searchTimeout = setTimeout(() => { this.renderWallets(allWallets, walletGrid, categoriesContainer, e.target.value, button, callback); }, 300); }); searchClear.addEventListener('click', () => { searchInput.value = ''; searchClear.style.display = 'none'; this.renderWallets(allWallets, walletGrid, categoriesContainer, '', button, callback); searchInput.focus(); }); }; // Store allWallets in outer scope for search functionality let allWallets = []; // Fetch wallet listings try { const listings = await this.fetchWalletListings(); this.walletListings = listings; // Smart merge with detected wallets (detected wallets can be empty) allWallets = this.smartMergeWallets(detectedWallets || [], listings); this.log('Total wallets after merge:', allWallets.length); this.log('Sample wallet:', allWallets[0]); // Update tab counts this.updateTabCounts(allWallets, filterTabs); // Filter tabs filterTabs.forEach(tab => { tab.addEventListener('click', () => { filterTabs.forEach(t => t.classList.remove('active')); tab.classList.add('active'); this.currentFilter = tab.dataset.filter; this.renderWallets(allWallets, walletGrid, categoriesContainer, searchInput.value, button, callback); this.trackEvent('filter_changed', { filter: this.currentFilter }); }); }); // Setup search setupSearch(); // Initial render this.renderWallets(allWallets, walletGrid, categoriesContainer, '', button, callback); // Setup keyboard navigation setupKeyboardNavigation(); // Focus search after animation setTimeout(() => searchInput.focus(), 300); this.measurePerformance('modal_open_start', 'modal_open_end'); } catch (error) { this.log('Error loading wallets:', error); // Use static wallet list as fallback const staticWallets = this.getStaticWalletList(); allWallets = this.smartMergeWallets(detectedWallets || [], { all: staticWallets, recommended: staticWallets.slice(0, 12) }); // Update tab counts this.updateTabCounts(allWallets, filterTabs); // Setup tabs filterTabs.forEach(tab => { tab.addEventListener('click', () => { filterTabs.forEach(t => t.classList.remove('active')); tab.classList.add('active'); this.currentFilter = tab.dataset.filter; this.renderWallets(allWallets, walletGrid, categoriesContainer, searchInput.value, button, callback); }); }); // Setup search setupSearch(); // Initial render with static list this.renderWallets(allWallets, walletGrid, categoriesContainer, '', button, callback); // Setup keyboard navigation setupKeyboardNavigation(); // Focus search after animation setTimeout(() => searchInput.focus(), 300); // Log final state this.log('Modal setup complete. Total wallets:', allWallets.length); this.log('Grid element:', walletGrid); this.log('Categories element:', categoriesContainer); } }, // Smart merge wallets with enhanced scoring smartMergeWallets: function(detectedWallets, listings) { const merged = [...detectedWallets]; const detectedNames = detectedWallets.map(w => w.name.toLowerCase()); const recentWallets = this.getRecentWallets(); // Add fetched wallets listings.all.forEach(wallet => { if (!detectedNames.includes(wallet.name.toLowerCase())) { // Determine the appropriate action for non-installed wallets const walletAction = this.getWalletAction(wallet); merged.push({ id: wallet.id, name: wallet.name, icon: wallet.icon, image_id: wallet.image_id, category: ['all'], provider: null, isFromApi: true, users: wallet.users || 0, popularity: wallet.popularity || 0, homepage: wallet.homepage, mobile_link: wallet.mobile?.universal || wallet.mobile?.native, desktop_link: wallet.desktop?.universal || wallet.desktop?.native, webapp_link: wallet.webapp?.universal, injected: wallet.injected, connect: async () => { // Handle non-installed wallet connection return this.handleNonInstalledWallet(wallet); } }); } else { // Update detected wallet with API data const detected = merged.find(w => w.name.toLowerCase() === wallet.name.toLowerCase()); if (detected) { detected.image_id = wallet.image_id || detected.image_id; detected.id = wallet.id || detected.id; detected.users = wallet.users || detected.users || 0; detected.popularity = wallet.popularity || 0; detected.icon = detected.icon || wallet.icon; } } }); // Ensure we have at least some popular wallets marked const popularWallets = ['MetaMask', 'Trust Wallet', 'Coinbase Wallet', 'Rainbow', 'Binance Web3 Wallet']; // Smart scoring system merged.forEach(wallet => { let score = 0; // Installed wallets get highest priority if (wallet.provider) { score += 10000; wallet.isInstalled = true; } // Recent wallets const recentIndex = recentWallets.indexOf(wallet.id || wallet.name); if (recentIndex >= 0) { score += 5000 - (recentIndex * 1000); wallet.isRecent = true; } // Recommended wallets if (listings.recommended.find(w => w.id === wallet.id) || popularWallets.includes(wallet.name)) { score += 2000; wallet.isRecommended = true; } // User count score if (wallet.users) { score += Math.log10(wallet.users) * 100; } // Popularity from API score += wallet.popularity || 0; wallet.score = score; }); // Sort by score merged.sort((a, b) => b.score - a.score); this.log('Merged wallets:', merged.length); this.log('Sample merged wallet:', merged[0]); return merged; }, // Get appropriate action for wallet getWalletAction: function(wallet) { const isMobile = this.isMobile(); if (isMobile && wallet.mobile_link) { return { type: 'deeplink', url: wallet.mobile_link }; } else if (!isMobile && wallet.desktop_link) { return { type: 'deeplink', url: wallet.desktop_link }; } else if (wallet.webapp_link) { return { type: 'webapp', url: wallet.webapp_link }; } else if (wallet.homepage) { return { type: 'homepage', url: wallet.homepage }; } return { type: 'walletconnect' }; }, // Handle non-installed wallet connection handleNonInstalledWallet: async function(wallet) { const action = this.getWalletAction(wallet); switch(action.type) { case 'deeplink': // Try to open wallet app window.location.href = action.url; this.showNotification(`Opening ${wallet.name}...`, 'info'); break; case 'webapp': // Open wallet web app window.open(action.url, '_blank'); this.showNotification(`Opening ${wallet.name} web app...`, 'info'); break; case 'homepage': // Show installation instructions this.showInstallationModal(wallet); break; case 'walletconnect': default: // Use WalletConnect protocol // TODO: Implement WalletConnect v2 QR code generation // This would require including @walletconnect/web3modal or @walletconnect/modal // For now, show a message about coming soon this.showNotification('WalletConnect QR code feature coming soon. Please install the wallet extension.', 'info'); // Show installation modal as fallback if (wallet.homepage) { this.showInstallationModal(wallet); } break; } throw new Error('Wallet not available'); }, // Show installation modal showInstallationModal: function(wallet) { const modal = document.createElement('div'); modal.className = 'rize-installation-modal'; const content = document.createElement('div'); content.className = 'rize-installation-content'; content.innerHTML = `
${wallet.image_id ? `${wallet.name}` : ''}

${wallet.name}

${wallet.name} is not installed on this device

${wallet.homepage ? ` Install ${wallet.name} ` : ''}

WalletConnect QR code support coming soon

`; modal.appendChild(content); document.body.appendChild(modal); // Store reference for closing this.installationModal = modal; // Close on backdrop click modal.addEventListener('click', (e) => { if (e.target === modal) { this.closeInstallationModal(); } }); // Close button content.querySelector('.wc-modal-close').addEventListener('click', () => { this.closeInstallationModal(); }); }, // Close installation modal closeInstallationModal: function() { if (this.installationModal) { this.installationModal.remove(); this.installationModal = null; } }, // Update tab counts updateTabCounts: function(wallets, tabs) { const counts = { all: wallets.length, installed: wallets.filter(w => w.isInstalled).length, popular: wallets.filter(w => w.isRecommended).length, recent: wallets.filter(w => w.isRecent).length }; tabs.forEach(tab => { const filter = tab.dataset.filter; const count = tab.querySelector('.tab-count'); if (count) { count.textContent = counts[filter] || '0'; } }); }, // Enhanced wallet rendering - simplified for debugging renderWallets: function(wallets, grid, categoriesContainer, searchTerm, button, callback) { this.log('Rendering wallets:', wallets.length, 'wallets, filter:', this.currentFilter, 'search:', searchTerm); grid.innerHTML = ''; categoriesContainer.innerHTML = ''; // Filter wallets let filtered = wallets; // Apply category filter if (this.currentFilter !== 'all') { switch(this.currentFilter) { case 'installed': filtered = wallets.filter(w => w.isInstalled); break; case 'popular': filtered = wallets.filter(w => w.isRecommended); break; case 'recent': filtered = wallets.filter(w => w.isRecent); break; } } this.log('Filtered wallets:', filtered.length); // Apply search filter if (searchTerm) { const search = searchTerm.toLowerCase(); filtered = filtered.filter(w => w.name.toLowerCase().includes(search) ); } // Show no results if (filtered.length === 0) { grid.innerHTML = `

No wallets found

Try searching with a different term

`; return; } // Create a simple grid for ALL wallets to ensure they show const simpleGrid = document.createElement('div'); simpleGrid.className = 'wc-wallet-grid'; simpleGrid.style.display = 'grid'; simpleGrid.style.gridTemplateColumns = 'repeat(4, 1fr)'; simpleGrid.style.gap = '12px'; simpleGrid.style.padding = '20px'; // Render ALL filtered wallets in a simple grid filtered.forEach((wallet, index) => { const walletItem = this.createSimpleWalletItem(wallet, index, button, callback); simpleGrid.appendChild(walletItem); }); grid.appendChild(simpleGrid); this.log('Rendered', filtered.length, 'wallet items'); }, // Create a simplified wallet item to ensure visibility createSimpleWalletItem: function(wallet, index, button, callback) { const item = document.createElement('div'); item.style.cssText = ` display: flex; flex-direction: column; align-items: center; gap: 8px; padding: 12px; background: rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.1); border-radius: 16px; cursor: pointer; transition: all 0.2s; min-width: 80px; min-height: 100px; `; // Icon wrapper const iconWrapper = document.createElement('div'); iconWrapper.style.cssText = ` width: 48px; height: 48px; border-radius: 12px; background: ${this.generateGradient(wallet.name)}; display: flex; align-items: center; justify-content: center; color: white; font-weight: bold; font-size: 20px; position: relative; overflow: hidden; `; // Try to add image const imageUrl = wallet.icon || this.getWalletImageUrl(wallet); if (imageUrl) { const img = document.createElement('img'); img.src = imageUrl; img.style.cssText = ` width: 100%; height: 100%; object-fit: contain; position: absolute; top: 0; left: 0; `; img.onerror = () => { img.style.display = 'none'; }; iconWrapper.appendChild(img); } // Fallback text const fallbackText = document.createElement('span'); fallbackText.textContent = wallet.name.substring(0, 2).toUpperCase(); fallbackText.style.zIndex = '0'; iconWrapper.appendChild(fallbackText); // Wallet name const name = document.createElement('div'); name.style.cssText = ` color: rgba(255, 255, 255, 0.9); font-size: 12px; font-weight: 600; text-align: center; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; `; name.textContent = wallet.name; // Add installed indicator if (wallet.isInstalled) { const indicator = document.createElement('div'); indicator.style.cssText = ` position: absolute; top: -4px; right: -4px; width: 16px; height: 16px; background: #10b981; border-radius: 50%; border: 2px solid #1a1a1a; `; iconWrapper.appendChild(indicator); } item.appendChild(iconWrapper); item.appendChild(name); // Hover effect item.addEventListener('mouseenter', () => { item.style.background = 'rgba(255, 255, 255, 0.1)'; item.style.transform = 'translateY(-2px)'; }); item.addEventListener('mouseleave', () => { item.style.background = 'rgba(255, 255, 255, 0.05)'; item.style.transform = 'translateY(0)'; }); // Click handler item.addEventListener('click', async () => { this.log('Wallet clicked:', wallet.name); // Close modal const overlay = document.querySelector('.rize-wallet-modal-overlay'); if (overlay) { overlay.remove(); this.isModalOpen = false; } if (button) { button.textContent = `Connecting to ${wallet.name}...`; button.disabled = true; } try { const address = await this.connectWithRetry(wallet); if (address) { this.storeRecentWallet(wallet.id || wallet.name); if (callback) { callback(address); } else if (button) { this.handleWalletConnected(address, button); } } } catch (error) { this.log('Connection error:', error); if (error.message !== 'Wallet not available') { const message = error.code === 4001 ? 'Connection cancelled by user' : 'Connection failed: ' + error.message; this.showNotification(message, 'error'); } if (button) { this.resetButton(button, 'Connect Wallet'); } } }); return item; }, // Create wallet section createWalletSection: function(title, wallets, button, callback) { this.log('Creating wallet section:', title, 'with', wallets.length, 'wallets'); const section = document.createElement('div'); section.className = 'wc-wallet-section'; const header = document.createElement('div'); header.className = 'wc-section-header'; header.innerHTML = `

${title}

`; const grid = document.createElement('div'); grid.className = 'wc-wallet-grid'; // Add test text to ensure grid is visible if (wallets.length === 0) { grid.innerHTML = '
No wallets in this section
'; } else { wallets.forEach((wallet, index) => { const item = this.createWalletItem(wallet, index, button, callback); grid.appendChild(item); }); } section.appendChild(header); section.appendChild(grid); return section; }, // Create enhanced wallet item createWalletItem: function(wallet, index, button, callback) { const walletItem = document.createElement('button'); walletItem.className = 'wc-wallet-item'; walletItem.type = 'button'; walletItem.setAttribute('aria-label', `Connect with ${wallet.name}`); walletItem.style.animationDelay = `${index * 20}ms`; // Data attributes for analytics walletItem.dataset.walletId = wallet.id; walletItem.dataset.walletName = wallet.name; // Create icon wrapper const iconWrapper = document.createElement('div'); iconWrapper.className = 'wc-wallet-icon-wrapper'; // Installed indicator if (wallet.isInstalled) { const installed = document.createElement('div'); installed.className = 'wc-installed-indicator'; installed.innerHTML = ''; iconWrapper.appendChild(installed); } // Recent badge if (wallet.isRecent && !wallet.isInstalled) { const badge = document.createElement('span'); badge.className = 'wc-recent-badge'; badge.textContent = 'Recent'; iconWrapper.appendChild(badge); } // Gradient fallback - ensure it's visible const fallback = document.createElement('div'); fallback.className = 'wc-wallet-icon-fallback'; fallback.style.background = this.generateGradient(wallet.name); fallback.textContent = wallet.name.substring(0, 2).toUpperCase(); fallback.style.display = 'flex'; // Ensure fallback is visible initially iconWrapper.appendChild(fallback); // Lazy loaded image const imageUrl = wallet.icon || this.getWalletImageUrl(wallet); if (imageUrl) { const img = document.createElement('img'); img.className = 'wc-wallet-icon'; img.alt = wallet.name; img.dataset.src = imageUrl; img.style.position = 'absolute'; img.style.top = '0'; img.style.left = '0'; img.style.width = '100%'; img.style.height = '100%'; iconWrapper.appendChild(img); } // Wallet info const info = document.createElement('div'); info.className = 'wc-wallet-info'; const name = document.createElement('span'); name.className = 'wc-wallet-name'; name.textContent = wallet.name; info.appendChild(name); if (wallet.users && wallet.users > 10000) { const users = document.createElement('span'); users.className = 'wc-wallet-users'; users.textContent = this.formatUserCount(wallet.users); info.appendChild(users); } walletItem.appendChild(iconWrapper); walletItem.appendChild(info); // Enhanced click handler walletItem.addEventListener('click', async () => { // Haptic feedback if (window.navigator.vibrate) { window.navigator.vibrate(10); } walletItem.classList.add('connecting'); // Track interaction this.trackEvent('wallet_clicked', { wallet: wallet.name, position: index, isInstalled: wallet.isInstalled || false, filter: this.currentFilter }); // Close modal const overlay = document.querySelector('.rize-wallet-modal-overlay'); if (overlay) { overlay.remove(); this.isModalOpen = false; } // Update connection status this.updateConnectionStatus(`Connecting to ${wallet.name}...`); if (button) { button.textContent = `Connecting to ${wallet.name}...`; button.disabled = true; } try { // Attempt connection with retry const address = await this.connectWithRetry(wallet); if (address) { // Store recent wallet this.storeRecentWallet(wallet.id || wallet.name); // Track successful connection this.trackEvent('wallet_connected', { wallet: wallet.name, retry_count: this.connectionRetries.get(wallet.id) || 0 }); if (callback) { callback(address); } else if (button) { this.handleWalletConnected(address, button); } } } catch (error) { this.log('Connection error:', error); // Track failed connection this.trackEvent('wallet_connection_failed', { wallet: wallet.name, error: error.message }); if (error.message !== 'Wallet not available') { const message = error.code === 4001 ? 'Connection cancelled by user' : 'Connection failed: ' + error.message; this.showNotification(message, 'error'); } if (button) { this.resetButton(button, 'Connect Wallet'); } } }); // Hover preview (desktop only) if (!this.isMobile()) { let hoverTimeout; walletItem.addEventListener('mouseenter', () => { hoverTimeout = setTimeout(() => { this.showWalletPreview(wallet, walletItem); }, 500); }); walletItem.addEventListener('mouseleave', () => { clearTimeout(hoverTimeout); this.hideWalletPreview(); }); } return walletItem; }, // Connection retry with exponential backoff connectWithRetry: async function(wallet) { const maxRetries = 3; const walletId = wallet.id || wallet.name; let lastError; for (let attempt = 0; attempt < maxRetries; attempt++) { try { this.connectionRetries.set(walletId, attempt); const address = await wallet.connect(); if (address) { this.updateConnectionStatus('Connected!', 'success'); return address; } } catch (error) { lastError = error; // User rejected - don't retry if (error.code === 4001) { this.updateConnectionStatus('Connection cancelled', 'error'); throw error; } this.log(`Connection attempt ${attempt + 1} failed:`, error); // Wait before retry with exponential backoff if (attempt < maxRetries - 1) { const delay = Math.pow(2, attempt) * 1000; this.updateConnectionStatus(`Retrying in ${delay/1000}s...`, 'warning'); await new Promise(resolve => setTimeout(resolve, delay)); } } } // All retries failed this.updateConnectionStatus('Connection failed', 'error'); throw lastError; }, // Update connection status updateConnectionStatus: function(message, type = 'info') { const statusEl = document.querySelector('.wc-connection-status'); if (statusEl) { const indicator = statusEl.querySelector('.status-indicator'); const text = statusEl.querySelector('.status-text'); // Update classes indicator.className = 'status-indicator ' + type; text.textContent = message; // Auto-hide success/error messages if (type === 'success' || type === 'error') { setTimeout(() => { text.textContent = 'Ready to connect'; indicator.className = 'status-indicator'; }, 3000); } } }, // Generate unique gradient for wallet generateGradient: function(name) { const gradients = [ ['#667eea', '#764ba2'], ['#f093fb', '#f5576c'], ['#4facfe', '#00f2fe'], ['#43e97b', '#38f9d7'], ['#fa709a', '#fee140'], ['#30cfd0', '#330867'], ['#a8edea', '#fed6e3'], ['#ff9a9e', '#fecfef'], ['#ffecd2', '#fcb69f'], ['#ff6e7f', '#bfe9ff'] ]; const index = name.charCodeAt(0) % gradients.length; const [c1, c2] = gradients[index]; return `linear-gradient(135deg, ${c1} 0%, ${c2} 100%)`; }, // Format user count formatUserCount: function(count) { if (count >= 1000000) { return (count / 1000000).toFixed(1) + 'M users'; } else if (count >= 1000) { return (count / 1000).toFixed(1) + 'K users'; } return count + ' users'; }, // Show wallet preview showWalletPreview: function(wallet, element) { const preview = document.createElement('div'); preview.className = 'wc-wallet-preview'; preview.innerHTML = `

${wallet.name}

${wallet.users ? `
Users ${this.formatUserCount(wallet.users)}
` : ''} ${wallet.isInstalled ? `
Status Installed
` : ''}
`; // Position preview const rect = element.getBoundingClientRect(); preview.style.left = rect.left + 'px'; preview.style.top = (rect.bottom + 10) + 'px'; // Adjust if off screen document.body.appendChild(preview); const previewRect = preview.getBoundingClientRect(); if (previewRect.right > window.innerWidth) { preview.style.left = (window.innerWidth - previewRect.width - 20) + 'px'; } if (previewRect.bottom > window.innerHeight) { preview.style.top = (rect.top - previewRect.height - 10) + 'px'; } // Show with animation setTimeout(() => { preview.classList.add('visible'); }, 10); // Store reference this.currentPreview = preview; }, // Hide wallet preview hideWalletPreview: function() { if (this.currentPreview) { this.currentPreview.classList.remove('visible'); setTimeout(() => { this.currentPreview.remove(); this.currentPreview = null; }, 200); } }, // Store recent wallet storeRecentWallet: function(walletId) { try { const recentKey = 'rize_recent_wallets'; let recent = JSON.parse(localStorage.getItem(recentKey) || '[]'); // Remove if already exists recent = recent.filter(id => id !== walletId); // Add to beginning recent.unshift(walletId); // Keep only last 5 recent = recent.slice(0, 5); localStorage.setItem(recentKey, JSON.stringify(recent)); } catch (e) { this.log('Failed to store recent wallet:', e); } }, // Get recent wallets getRecentWallets: function() { try { const recentKey = 'rize_recent_wallets'; return JSON.parse(localStorage.getItem(recentKey) || '[]'); } catch (e) { return []; } }, // Analytics tracking trackEvent: function(eventName, data = {}) { if (!CONFIG.analytics) return; const eventData = { event: eventName, timestamp: Date.now(), ...data }; // Send to Google Analytics if available if (window.gtag) { gtag('event', eventName, eventData); } // Update WordPress stats if (eventName === 'wallet_connected') { // Increment connection count fetch('https://www.rizefc.com/wp-admin/admin-ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'action=rize_track_connection&wallet=' + encodeURIComponent(data.wallet) }); } this.log('[Analytics]', eventName, eventData); }, // Get user preferences getUserPreferences: function() { try { return JSON.parse(localStorage.getItem('rize_wallet_preferences') || '{}'); } catch { return {}; } }, // Save user preferences saveUserPreferences: function(preferences) { try { localStorage.setItem('rize_wallet_preferences', JSON.stringify(preferences)); } catch (e) { this.log('Failed to save preferences:', e); } }, // Initialize token page functionality initTokenPage: function() { this.log('Initializing token page...'); // Replace connect buttons const connectElements = document.querySelectorAll('a[href*="connect"], button:contains("Connect"), a:contains("Connect Wallet")'); const allElements = document.querySelectorAll('a, button'); allElements.forEach(element => { const text = element.textContent.toLowerCase(); if ((text.includes('connect') && text.includes('wallet')) || text === 'connect wallet') { this.log('Found potential connect element:', element); // Replace with custom button const newButton = document.createElement('button'); newButton.className = 'rize-token-connect-button'; newButton.textContent = 'Connect Wallet'; newButton.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); this.connectWalletForToken(newButton); }); element.parentNode.replaceChild(newButton, element); } }); // Check existing connection if (this.checkExistingConnection()) { this.showSwapInterface(); } }, // Check if wallet is already connected checkExistingConnection: function() { if (typeof window.ethereum !== 'undefined' && window.ethereum.selectedAddress) { this.connectedAddress = window.ethereum.selectedAddress; return true; } return false; }, // Connect wallet for token operations connectWalletForToken: async function(button) { this.log('Connecting wallet for token operations...'); const originalText = button.textContent; button.textContent = 'CONNECTING...'; button.disabled = true; try { const wallets = this.detectWallets(); if (wallets.length === 0) { this.showNotification('No Web3 wallet detected. Please install MetaMask or another Web3 wallet.', 'error'); this.resetButton(button, originalText); return; } let address; if (wallets.length === 1 || this.isMobile()) { address = await wallets[0].connect(); } else { address = await this.showWalletSelectionForToken(wallets); } if (address) { this.connectedAddress = address; button.textContent = 'Connected: ' + address.substring(0, 6) + '...' + address.substring(address.length - 4); button.style.backgroundColor = '#4caf50'; this.showSwapInterface(); button.onclick = () => { if (confirm('Disconnect wallet?')) { this.disconnectWallet(button); } }; } } catch (error) { this.log('Connection error:', error); this.showNotification(error.message || 'Connection failed', 'error'); this.resetButton(button, originalText); } }, // Show wallet selection for token operations showWalletSelectionForToken: function(wallets) { return new Promise((resolve, reject) => { this.showWalletSelection(wallets, null, (address) => { resolve(address); }); }); }, // Show swap interface showSwapInterface: function() { this.log('Showing swap interface...'); if (document.querySelector('.rize-token-swap-interface')) { return; } const connectButton = document.querySelector('.rize-token-connect-button'); if (!connectButton) return; const swapInterface = document.createElement('div'); swapInterface.className = 'rize-token-swap-interface'; swapInterface.innerHTML = `

Buy ${CONFIG.token.symbol} Tokens

You will receive approximately:

0 ${CONFIG.token.symbol}

Buy on Jupiter (Solana) →
`; connectButton.parentNode.insertBefore(swapInterface, connectButton.nextSibling); // Add event handlers const ethInput = document.getElementById('ethAmount'); const tokenAmountSpan = document.getElementById('tokenAmount'); const swapButton = document.getElementById('swapButton'); ethInput.addEventListener('input', (e) => { const ethAmount = parseFloat(e.target.value) || 0; if (ethAmount > 0) { // Simple calculation - implement actual price fetching const tokenAmount = ethAmount * 1000; // Example rate tokenAmountSpan.textContent = tokenAmount.toFixed(2); swapButton.disabled = false; swapButton.textContent = `Buy ${CONFIG.token.symbol} Tokens`; } else { tokenAmountSpan.textContent = '0'; swapButton.disabled = true; swapButton.textContent = `Enter Amount to Buy ${CONFIG.token.symbol}`; } }); swapButton.addEventListener('click', () => { this.executeSwap(); }); }, // Execute token swap executeSwap: async function() { const ethAmount = document.getElementById('ethAmount').value; const swapButton = document.getElementById('swapButton'); if (!ethAmount || parseFloat(ethAmount) <= 0) { this.showNotification('Please enter a valid amount', 'warning'); return; } swapButton.disabled = true; swapButton.textContent = 'Processing...'; try { if (!CONFIG.token.contract) { this.showNotification('Token contract address not configured. Please contact administrator.', 'error'); return; } const txHash = await this.sendTransaction(ethAmount); if (txHash) { this.showNotification(`Transaction submitted! Hash: ${txHash}`, 'success'); document.getElementById('ethAmount').value = ''; document.getElementById('tokenAmount').textContent = '0'; } } catch (error) { this.log('Swap error:', error); this.showNotification('Transaction failed: ' + error.message, 'error'); } finally { swapButton.disabled = false; swapButton.textContent = `Buy ${CONFIG.token.symbol} Tokens`; } }, // Send transaction sendTransaction: async function(ethAmount) { if (!window.ethereum) { throw new Error('No wallet connected'); } const accounts = await window.ethereum.request({ method: 'eth_accounts' }); if (!accounts || accounts.length === 0) { throw new Error('No account connected'); } const valueInWei = '0x' + (parseFloat(ethAmount) * 1e18).toString(16); const transactionParameters = { to: CONFIG.token.contract || '0x0000000000000000000000000000000000000000', from: accounts[0], value: valueInWei, data: '0x', // Encode swap function call here }; try { const txHash = await window.ethereum.request({ method: 'eth_sendTransaction', params: [transactionParameters], }); return txHash; } catch (error) { throw error; } }, // Disconnect wallet disconnectWallet: function(button) { this.connectedAddress = null; button.textContent = 'Connect Wallet'; button.style.backgroundColor = ''; button.onclick = (e) => { e.preventDefault(); this.connectWalletForToken(button); }; const swapInterface = document.querySelector('.rize-token-swap-interface'); if (swapInterface) { swapInterface.remove(); } }, // Add wallet button to login forms addWalletButton: function() { this.log('Looking for login forms...'); const forms = document.querySelectorAll('form'); this.log('Found forms:', forms.length); forms.forEach((form, index) => { const passwordField = form.querySelector('input[type="password"]'); const existingButton = form.querySelector('.rize-wallet-connect-button'); if (passwordField && !existingButton) { this.log(`Adding wallet button to form ${index}`); const container = document.createElement('div'); container.className = 'rize-wallet-connect-container'; const divider = document.createElement('div'); divider.className = 'divider-or'; divider.innerHTML = `
or `; container.appendChild(divider); const button = document.createElement('button'); button.type = 'button'; button.className = 'rize-wallet-connect-button'; button.innerHTML = ` Connect Wallet `; button.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); e.stopImmediatePropagation(); this.log('Button clicked'); this.connectWallet(button); }); container.appendChild(button); const submitButton = form.querySelector('button[type="submit"], input[type="submit"], .button, button#log-in, input#log-in'); const lostPassword = form.querySelector('a[href*="lost-password"], .lost-password'); if (lostPassword && lostPassword.parentElement) { lostPassword.parentElement.parentNode.insertBefore(container, lostPassword.parentElement); } else if (submitButton && submitButton.parentElement) { submitButton.parentElement.parentNode.insertBefore(container, submitButton.parentElement.nextSibling); } else { form.appendChild(container); } this.log('Wallet button added successfully'); } }); }, // Connect wallet function connectWallet: async function(button) { this.log('Connect wallet called'); if (button.disabled || this.isModalOpen) { this.log('Button disabled or modal already open'); return; } const originalText = button.innerHTML; button.innerHTML = ` Loading Wallets... `; button.disabled = true; try { await new Promise(resolve => setTimeout(resolve, 300)); const detectedWallets = this.detectWallets(); this.log('Detected wallets:', detectedWallets.map(w => w.name)); // Always show wallet selection modal regardless of detected wallets // This follows WalletConnect best practices this.showWalletSelection(detectedWallets, button); } catch (error) { this.log('Error in connectWallet:', error); this.showNotification(error.message || 'Connection failed', 'error'); this.resetButton(button, originalText); } }, // Detect available wallets detectWallets: function() { const wallets = []; // Check for MetaMask if (typeof window.ethereum !== 'undefined' && window.ethereum.isMetaMask) { this.log('MetaMask detected'); wallets.push({ name: 'MetaMask', icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjEyIiBoZWlnaHQ9IjE4OSIgdmlld0JveD0iMCAwIDIxMiAxODkiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0xOTguODAzIDE4LjI5OTlMMTE3LjI1MSA3OC41NDk5TDEzMi40NzEgNDIuNDQ5OUwxOTguODAzIDE4LjI5OTlaIiBmaWxsPSIjRTI3NjI2Ii8+CjxwYXRoIGQ9Ik0xMi40NzUgMTguMjk5OUw5My41MjcgNzguOTY5OUw3OC43NTcgNDIuNDQ5OUwxMi40NzUgMTguMjk5OVoiIGZpbGw9IiNFMjc2MjYiLz4KPHBhdGggZD0iTTE3MC4xMjUgMTMwLjAyTDE0NC4yNzUgMTU3LjExTDE5Ny40ODUgMTcyLjU1TDIxNC40MDUgMTMxLjAyTDE3MC4xMjUgMTMwLjAyWiIgZmlsbD0iI0UyNzYyNiIvPgo8cGF0aCBkPSJNNDEuODQ1IDEzMC4wMkwtMi40MzUgMTMxLjAyTDE0LjQwNSAxNzIuNTVMNjcuNzI1IDE1Ny4xMUw0MS44NDUgMTMwLjAyWiIgZmlsbD0iI0UyNzYyNiIvPgo8cGF0aCBkPSJNNjUuNjQ1IDkwLjAzTDUyLjQzNSA5OS43NEw5NC44NTUgMTAxLjg4TDgxLjk1NSA1NC45N0w2NS42NDUgOTAuMDNaIiBmaWxsPSIjRTI3NjI2Ii8+CjxwYXRoIGQ9Ik0xNDUuNjI1IDkwLjAzTDEyOS4wNjUgNTQuNTVMMTE2LjQzNSAxMDEuODhMMTU4Ljg1NSA5OS43NEwxNDUuNjI1IDkwLjAzWiIgZmlsbD0iI0UyNzYyNiIvPgo8cGF0aCBkPSJNNjcuNzI1IDE1Ny4xMUw4MC4zNTUgMTA5Ljc4TDQ1LjE1NSAxMDguNjJMNjcuNzI1IDE1Ny4xMVoiIGZpbGw9IiNFMjc2MjYiLz4KPHBhdGggZD0iTTE0NC4yNzUgMTU3LjExTDE2Ni44NDUgMTA4LjYyTDEzMS44NTUgMTA5Ljc4TDE0NC4yNzUgMTU3LjExWiIgZmlsbD0iI0UyNzYyNiIvPgo8cGF0aCBkPSJNMTY2Ljg0NSAxMDguNjJMMTQ0LjI3NSAxNTcuMTFMMTQ1LjYyNSA5MC4wM0wxNjYuODQ1IDEwOC42MloiIGZpbGw9IiNENzdDMUIiLz4KPHBhdGggZD0iTTQ1LjE1NSAxMDguNjJMNjUuNjQ1IDkwLjAzTDY3LjcyNSAxNTcuMTFMNDUuMTU1IDEwOC42MloiIGZpbGw9IiNENzdDMUIiLz4KPHBhdGggZD0iTTk0Ljg1NSAxMDEuODhMODEuOTU1IDU0Ljk3TDkzLjUyNyA3OC45N0w5NC44NTUgMTAxLjg4WiIgZmlsbD0iI0U3NzUyNSIvPgo8cGF0aCBkPSJNMTE2LjQzNSAxMDEuODhMMTE3LjI1MSA3OC41NUwxMjkuMDY1IDU0LjU1TDExNi40MzUgMTAxLjg4WiIgZmlsbD0iI0U3NzUyNSIvPgo8cGF0aCBkPSJNNjcuNzI1IDE1Ny4xMUw4MC4zNTUgMTA5Ljc4TDgxLjUyNSAxNTAuNDFMNjcuNzI1IDE1Ny4xMVoiIGZpbGw9IiNGNjg1MUYiLz4KPHBhdGggZD0iTTE0NC4yNzUgMTU3LjExTDEzMC40NzUgMTUwLjQxTDEzMS44NTUgMTA5Ljc4TDE0NC4yNzUgMTU3LjExWiIgZmlsbD0iI0Y2ODUxRiIvPgo8cGF0aCBkPSJNNTIuNDM1IDk5Ljc0TDY1LjY0NSA5MC4wM0w0NS4xNTUgMTA4LjYyTDUyLjQzNSA5OS43NFoiIGZpbGw9IiNDMDM5M0YiLz4KPHBhdGggZD0iTTE1OC44NTUgOTkuNzRMMTY2Ljg0NSAxMDguNjJMMTQ1LjYyNSA5MC4wM0wxNTguODU1IDk5Ljc0WiIgZmlsbD0iI0MwMzkzRiIvPgo8cGF0aCBkPSJNODAuMzU1IDEwOS43OEw2Ny43MjUgMTU3LjExTDQ1LjE1NSAxMDguNjJMODAuMzU1IDEwOS43OFoiIGZpbGw9IiNGNjg1MUYiLz4KPHBhdGggZD0iTTEzMS44NTUgMTA5Ljc4TDE2Ni44NDUgMTA4LjYyTDE0NC4yNzUgMTU3LjExTDEzMS44NTUgMTA5Ljc4WiIgZmlsbD0iI0Y2ODUxRiIvPgo8cGF0aCBkPSJNMTk3LjQ4NSAxNzIuNTVMMTQ0LjI3NSAxNTcuMTFMMTY2Ljg0NSAxMDguNjJMMTk3LjQ4NSAxNzIuNTVaIiBmaWxsPSIjRTU3NTI0Ii8+CjxwYXRoIGQ9Ik0xNC40MDUgMTcyLjU1TDQ1LjE1NSAxMDguNjJMNjcuNzI1IDE1Ny4xMUwxNC40MDUgMTcyLjU1WiIgZmlsbD0iI0U1NzUyNCIvPgo8cGF0aCBkPSJNMjE0LjQwNSAxMzEuMDJMMTk3LjQ4NSAxNzIuNTVMMjA2LjkxNSAxODQuNTlMMjI5LjM5NSAxNzMuMjdMMjE0LjQwNSAxMzEuMDJaIiBmaWxsPSIjRTU3NTI0Ii8+CjxwYXRoIGQ9Ik0tMi40MzUgMTMxLjAyTC0xNy40MjUgMTczLjI3TDQuODk1IDE4NC41OUwxNC40MDUgMTcyLjU1TC0yLjQzNSAxMzEuMDJaIiBmaWxsPSIjRTU3NTI0Ii8+CjxwYXRoIGQ9Ik0xOTguODAzIDE4LjI5OTlMMTMyLjQ3MSA0Mi40NDk5TDEyOS4wNjUgNTQuNTQ5OUwxOTguODAzIDE4LjI5OTlaIiBmaWxsPSIjNzYzRTE0Ii8+CjxwYXRoIGQ9Ik0xMi40NzUgMTguMjk5OUw4MS45NTUgNTQuOTdMNzguNzU3IDQyLjQ1TDEyLjQ3NSAxOC4yOTk5WiIgZmlsbD0iIzc2M0UxNCIvPgo8cGF0aCBkPSJNNjcuNzI1IDE1Ny4xMUw4MS41MjUgMTUwLjQxTDgwLjU3NSAxNjQuNjNMNjcuNzI1IDE1Ny4xMVoiIGZpbGw9IiNFNDc1MjQiLz4KPHBhdGggZD0iTTE0NC4yNzUgMTU3LjExTDEzMS40MjUgMTY0LjYzTDEzMC40NzUgMTUwLjQxTDE0NC4yNzUgMTU3LjExWiIgZmlsbD0iI0U0NzUyNCIvPgo8cGF0aCBkPSJNMjI5LjM5NSAxNzMuMjdMMjA2LjkxNSAxODQuNTlMMjA4LjU1NSAxNjguNDlMMjI5LjM5NSAxNzMuMjdaIiBmaWxsPSIjRDc3QzFCIi8+CjxwYXRoIGQ9Ik0tMTcuNDI1IDE3My4yN0wzLjQxNSAxNjguNDlMNC44OTUgMTg0LjU5TC0xNy40MjUgMTczLjI3WiIgZmlsbD0iI0Q3N0MxQiIvPgo8cGF0aCBkPSJNMTEwLjc3NSAxMTYuNjJMOTQuODU1IDEwMS44OEw5NS4zODUgMTA4LjYyTDExMC43NzUgMTE2LjYyWiIgZmlsbD0iI0Y2ODUxRiIvPgo8cGF0aCBkPSJNMTAwLjQ3NSAxMTYuNjJMMTE1Ljg2NSAxMDguNjJMMTE2LjQzNSAxMDEuODhMMTAwLjQ3NSAxMTYuNjJaIiBmaWxsPSIjRjY4NTFGIi8+CjxwYXRoIGQ9Ik0xNDQuMjc1IDE1Ny4xMUwxOTcuNDg1IDE3Mi41NUwyMDguNTU1IDE2OC40OUwxNDQuMjc1IDE1Ny4xMVoiIGZpbGw9IiNGNjg1MUYiLz4KPHBhdGggZD0iTTY3LjcyNSAxNTcuMTFMMy40MTUgMTY4LjQ5TDE0LjQwNSAxNzIuNTVMNjcuNzI1IDE1Ny4xMVoiIGZpbGw9IiNGNjg1MUYiLz4KPHBhdGggZD0iTTY3LjcyNSAxNTcuMTFMODAuNTc1IDE2NC42M0w3Mi44NDUgMTc4LjhMNjcuNzI1IDE1Ny4xMVoiIGZpbGw9IiNFNTc1MjQiLz4KPHBhdGggZD0iTTE0NC4yNzUgMTU3LjExTDEzOS4xNTUgMTc4LjhMMTMxLjQyNSAxNjQuNjNMMTQ0LjI3NSAxNTcuMTFaIiBmaWxsPSIjRTU3NTI0Ii8+CjxwYXRoIGQ9Ik00LjE0NSAxODQuNTlMMTQuNDA1IDE3Mi41NUw3Mi44NDUgMTc4LjhMNC4xNDUgMTg0LjU5WiIgZmlsbD0iI0YwNzA1QSIvPgo8cGF0aCBkPSJNMTM5LjE1NSAxNzguOEwxOTcuNDg1IDE3Mi41NUwyMDcuMTA1IDE4NC41OUwxMzkuMTU1IDE3OC44WiIgZmlsbD0iI0YwNzA1QSIvPgo8cGF0aCBkPSJNNzIuODQ1IDE3OC44TDczLjM1NSAxODQuNDZMNjcuNzI1IDE4NS4yNkw0LjE0NSAxODQuNTlMNzIuODQ1IDE3OC44WiIgZmlsbD0iI0M5NDAzQSIvPgo8cGF0aCBkPSJNMTM5LjE1NSAxNzguOEwyMDcuMTA1IDE4NC41OUwxNDQuMDE1IDE4NS4yNkwxMzguNTY1IDE4NC40NkwxMzkuMTU1IDE3OC44WiIgZmlsbD0iI0M5NDAzQSIvPgo8cGF0aCBkPSJNMTMwLjQ3NSAxNTAuNDFMMTMxLjQyNSAxNjQuNjNMMTM4LjU2NSAxODQuNDZMMTM5LjE1NSAxNzguOEwxMzAuNDc1IDE1MC40MVoiIGZpbGw9IiNFMjc2MjYiLz4KPHBhdGggZD0iTTcyLjg0NSAxNzguOEw3My4zNTUgMTg0LjQ2TDgwLjU3NSAxNjQuNjNMODEuNTI1IDE1MC40MUw3Mi44NDUgMTc4LjhaIiBmaWxsPSIjRTI3NjI2Ii8+CjxwYXRoIGQ9Ik04MS45NTUgNTQuOTdMOTQuODU1IDEwMS44OEw1Mi40MzUgOTkuNzRMODEuOTU1IDU0Ljk3WiIgZmlsbD0iI0Y2ODUxRiIvPgo8cGF0aCBkPSJNMTI5LjA2NSA1NC41NUwxNTguODU1IDk5Ljc0TDExNi40MzUgMTAxLjg4TDEyOS4wNjUgNTQuNTVaIiBmaWxsPSIjRjY4NTFGIi8+CjxwYXRoIGQ9Ik0xMDUuNTI1IDExNi4wMkwxMDAuNDc1IDExNi42MkwxMTYuNDM1IDEwMS44OEwxMDUuNTI1IDExNi4wMloiIGZpbGw9IiNFMjc2MjYiLz4KPHBhdGggZD0iTTEwNS43NzUgMTE2LjAyTDk0Ljg1NSAxMDEuODhMMTEwLjc3NSAxMTYuNjJMMTA1Ljc3NSAxMTYuMDJaIiBmaWxsPSIjRTI3NjI2Ii8+CjxwYXRoIGQ9Ik0xMzguNTY1IDE4NC40NkwxNDQuMDE1IDE4NS4yNkgxNDQuMjc1TDEzOC41NjUgMTg0LjQ2WiIgZmlsbD0iI0Y2ODUxRiIvPgo8cGF0aCBkPSJNNjcuNzI1IDE4NS4yNkw3My4zNTUgMTg0LjQ2TDY3LjcyNSAxODUuMjZaIiBmaWxsPSIjRjY4NTFGIi8+Cjwvc3ZnPg==', id: 'c57ca95b47569778a828d19178114f4db188b89b763c899ba0be274e97267d96', category: ['popular', 'mobile', 'desktop'], provider: window.ethereum, connect: async () => { const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); return accounts[0]; } }); } // Check for Trust Wallet if (window.trustwallet) { this.log('Trust Wallet detected'); wallets.push({ name: 'Trust Wallet', icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTMyIDY0QzQ5LjY3MzEgNjQgNjQgNDkuNjczMSA2NCAzMkM2NCAxNC4zMjY5IDQ5LjY3MzEgMCAzMiAwQzE0LjMyNjkgMCAwIDE0LjMyNjkgMCAzMkMwIDQ5LjY3MzEgMTQuMzI2OSA2NCAzMiA2NFoiIGZpbGw9IiMzMzc1QkIiLz4KPHBhdGggZD0iTTMxLjU1MiAxOC4wNDhDMzcuODg4IDE4LjA0OCA0My4wMDggMjMuMTY4IDQzLjAwOCAyOS41MDRDNDMuMDA4IDI5LjY5NiA0My4wMDggMjkuODg4IDQzLjAwOCAzMC4wOEM0MyAzNC44IDQxLjA3MiAzOS4wODggMzcuODg4IDQyLjI3MkMzNy43NiA0Mi40IDM3LjU2OCA0Mi40NzIgMzcuMzc2IDQyLjQ3MkgzMS41NTJDMzEuMzYgNDIuNDcyIDMxLjE2OCA0Mi40IDMxLjA0IDQyLjI3MkMyNy44NTYgMzkuMDg4IDI1LjkyOCAzNC44IDI1LjkyIDMwLjA4QzI1LjkyIDI5Ljg4OCAyNS45MiAyOS42OTYgMjUuOTIgMjkuNTA0QzI1LjkyIDIzLjE2OCAzMS4wNDggMTguMDQ4IDMxLjU1MiAxOC4wNDhaIiBmaWxsPSJ3aGl0ZSIvPgo8L3N2Zz4=', id: '4622a2b2d6af1c9844944291e5e7351a6aa24cd7b23099efac1b2fd875da31a0', category: ['popular', 'mobile'], provider: window.trustwallet, connect: async () => { const accounts = await window.trustwallet.request({ method: 'eth_requestAccounts' }); return accounts[0]; } }); } // Check for Coinbase Wallet if (window.ethereum && window.ethereum.isCoinbaseWallet) { this.log('Coinbase Wallet detected'); wallets.push({ name: 'Coinbase Wallet', icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTE2IDBBIDE2IDE2IDAgMSAwIDE2IDMyQTE2IDE2IDAgMSAwIDE2IDBaIiBmaWxsPSIjMTY1MkYwIi8+CjxwYXRoIGQ9Ik0xNiA3QzExLjAyOTQgNyA3IDExLjAyOTQgNyAxNkM3IDIwLjk3MDYgMTEuMDI5NCAyNSAxNiAyNUMyMC45NzA2IDI1IDI1IDIwLjk3MDYgMjUgMTZDMjUgMTEuMDI5NCAyMC45NzA2IDcgMTYgN1pNMTkuNSAxN0gxNFYxNUgxOS41VjE3WiIgZmlsbD0id2hpdGUiLz4KPC9zdmc+', id: 'fd20dc426fb37566d803205b19bbc1d4096b248ac04548e3cfb6b3a38bd033aa', category: ['popular', 'mobile', 'desktop'], provider: window.ethereum, connect: async () => { const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); return accounts[0]; } }); } // Check for WalletConnect (generic) if (window.ethereum && !window.ethereum.isMetaMask && !window.ethereum.isCoinbaseWallet) { this.log('Generic Web3 wallet detected'); wallets.push({ name: 'Injected Wallet', icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNjQiIHZpZXdCb3g9IjAgMCA2NCA2NCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGNpcmNsZSBjeD0iMzIiIGN5PSIzMiIgcj0iMzIiIGZpbGw9IiMzMzc1QkIiLz4KPHBhdGggZD0iTTIwIDI0VjQwSDQ0VjI0SDIwWiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyIi8+CjxwYXRoIGQ9Ik0yMCAzMkg0NCIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyIi8+CjxjaXJjbGUgY3g9IjMyIiBjeT0iMzIiIHI9IjQiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPg==', category: ['desktop'], provider: window.ethereum, connect: async () => { const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' }); return accounts[0]; } }); } this.log('Total detected wallets:', wallets.length); return wallets; }, // Handle successful wallet connection handleWalletConnected: async function(address, button) { this.log('Wallet connected:', address); const shortAddress = address.substring(0, 6) + '...' + address.substring(address.length - 4); button.innerHTML = ` Connected: ${shortAddress} `; button.classList.add('connected'); button.disabled = false; this.showNotification('Wallet connected successfully! Creating account...', 'success'); // Create WordPress account this.createWordPressAccount(address); }, // Create WordPress account with wallet address createWordPressAccount: async function(address) { this.log('Creating WordPress account for:', address); try { const response = await fetch('https://www.rizefc.com/wp-admin/admin-ajax.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, body: 'action=rize_wallet_login&address=' + encodeURIComponent(address) + '&nonce=' + '71d85b9752' }); const data = await response.json(); if (data.success) { this.showNotification('Login successful! Redirecting...', 'success'); window.location.href = data.redirect_url || 'https://www.rizefc.com'; } else { this.showNotification(data.message || 'Login failed', 'error'); } } catch (error) { this.log('Account creation error:', error); this.showNotification('Failed to create account', 'error'); } }, // Reset button state resetButton: function(button, originalContent) { button.innerHTML = originalContent; button.disabled = false; button.classList.remove('connected'); }, // Check if mobile isMobile: function() { return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent) || window.innerWidth <= 768; } }; // Initialize when DOM is ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { RizeWalletConnect.init(); }); } else { RizeWalletConnect.init(); } // Re-check for login forms after dynamic content loads let observer = new MutationObserver(function(mutations) { RizeWalletConnect.addWalletButton(); }); observer.observe(document.body, { childList: true, subtree: true }); // Export to global scope for debugging window.RizeWalletConnect = RizeWalletConnect; })();