diff --git a/Artifact/Artifact.crx b/Artifact/Artifact.crx index c4da462bd..b51c1cfc5 100644 Binary files a/Artifact/Artifact.crx and b/Artifact/Artifact.crx differ diff --git a/Artifact/repo/Artifact.crx b/Artifact/repo/Artifact.crx index c4da462bd..b51c1cfc5 100644 Binary files a/Artifact/repo/Artifact.crx and b/Artifact/repo/Artifact.crx differ diff --git a/Artifact/repo/package-lock.json b/Artifact/repo/package-lock.json index c85f14a6e..a717740f8 100644 --- a/Artifact/repo/package-lock.json +++ b/Artifact/repo/package-lock.json @@ -9291,26 +9291,6 @@ "lodash.uniq": "^4.5.0" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001659", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001659.tgz", - "integrity": "sha512-Qxxyfv3RdHAfJcXelgf0hU4DFUVXBGTjqrBUZLUh8AtlGnsDo+CnncYtTd95+ZKfnANUOzxyIQCuU/UeBZBYoA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, "node_modules/case-sensitive-paths-webpack-plugin": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz", @@ -25656,4 +25636,4 @@ } } } -} +} \ No newline at end of file diff --git a/Artifact/repo/public/background.js b/Artifact/repo/public/background.js index 9d174e8ae..68148fd1b 100644 --- a/Artifact/repo/public/background.js +++ b/Artifact/repo/public/background.js @@ -400,4 +400,11 @@ function setupRefreshTokenTimer() { } else { console.log('⚠️ No refresh token available, timer not set'); } -} \ No newline at end of file +} + +chrome.alarms.create('tokenRefresh', { periodInMinutes: 55 }); +chrome.alarms.onAlarm.addListener((alarm) => { + if (alarm.name === 'tokenRefresh') { + refreshAuthToken(); + } +}); \ No newline at end of file diff --git a/Artifact/repo/src/components/RelicDAODashboard.js b/Artifact/repo/src/components/RelicDAODashboard.js index 74fde3277..bf604bce6 100644 --- a/Artifact/repo/src/components/RelicDAODashboard.js +++ b/Artifact/repo/src/components/RelicDAODashboard.js @@ -12,7 +12,7 @@ import axios from 'axios'; import { useNavigate } from 'react-router-dom'; import { Sheet } from 'react-modal-sheet'; import { ArrowLeftIcon } from '@heroicons/react/24/solid'; -import { getUserProfile, loadWallet } from '../lib/api'; +import { getUserProfile, loadWallet, refreshAuthToken } from '../lib/api'; import twitterBanner from '../images/rb_45418.png'; import { createThirdwebClient } from 'thirdweb'; // import { useActiveAccount } from 'thirdweb/react'; @@ -243,26 +243,45 @@ const RelicDAODashboard = () => { // Add new function to sync tokens const syncAuthToken = async () => { + const chromeStorage = await chrome.storage.local.get(['authToken', 'refreshToken']); const localToken = localStorage.getItem('authToken'); - - const chromeStorage = await chrome.storage.local.get(['authToken']); - - const chromeToken = chromeStorage.authToken; - + const localRefreshToken = localStorage.getItem('refreshToken'); - const localrefreshToken = localStorage.getItem('refreshToken'); - const chromerefreshToken = chromeStorage.refreshToken; - - if (chromeToken && chromeToken !== localToken) { + if (chromeStorage.authToken && chromeStorage.authToken !== localToken) { console.log('🔄 Syncing auth token from chrome storage to local storage'); - console.log('🔑 Chrome storage , local storage and chrome token:',{chromeToken,localToken,chromeStorage,localrefreshToken,chromerefreshToken}); - - localStorage.setItem('authToken', chromeToken); - localStorage.setItem('refreshToken', chromerefreshToken); + localStorage.setItem('authToken', chromeStorage.authToken); + localStorage.setItem('refreshToken', chromeStorage.refreshToken); console.log('✅ Auth token synced'); - return chromeToken; } - return localToken; + + // Check if token is expired by decoding JWT + const token = localStorage.getItem('authToken'); + if (token && token !== 'null') { + try { + // Split the token and decode the payload (middle part) + const tokenParts = token.split('.'); + if (tokenParts.length === 3) { + // Base64 decode and parse as JSON + const payload = JSON.parse(atob(tokenParts[1])); + const expiryTime = payload.exp * 1000; // Convert to milliseconds + + // If token is expired or about to expire in the next 5 minutes + if (Date.now() >= expiryTime - 300000) { // 5 min buffer + console.warn('⚠️ Token expired or about to expire, refreshing...'); + const refreshResult = await refreshAuthToken(); + console.log('🔑 Refresh from dashboard result:', refreshResult); + if (refreshResult && refreshResult.authToken) { + console.log('✅ Token refreshed successfully'); + return refreshResult.authToken; + } + } + } + } catch (error) { + console.error('❌ Error checking token expiration:', error); + } + } + + return token; }; useEffect(() => { @@ -340,12 +359,6 @@ const RelicDAODashboard = () => { } catch (error) { console.error('Error fetching data:', error); // If there's an auth error, clear the storage - if (error.response?.status === 401) { - chrome.storage.local.set({ - authToken: null, - isLoggedIn: false - }); - } } } }; diff --git a/Artifact/repo/src/components/WidgetDashboard.js b/Artifact/repo/src/components/WidgetDashboard.js index 2a5321b56..430fdeb49 100644 --- a/Artifact/repo/src/components/WidgetDashboard.js +++ b/Artifact/repo/src/components/WidgetDashboard.js @@ -1,3 +1,4 @@ +/*global chrome*/ import React, { useState, useEffect } from 'react'; import { IoInformationCircleOutline } from "react-icons/io5"; import starIcon from '../images/star.png'; @@ -10,10 +11,26 @@ function WidgetDashboard() { const [level, setLevel] = useState(null); const [sparks, setSparks] = useState(null); + // Add this syncAuthToken function from your dashboard + const syncAuthToken = async () => { + const chromeStorage = await chrome.storage.local.get(['authToken', 'refreshToken']); + const localToken = localStorage.getItem('authToken'); + + if (chromeStorage.authToken && chromeStorage.authToken !== localToken) { + console.log('🔄 Widget: Syncing auth token from chrome storage to local storage'); + localStorage.setItem('authToken', chromeStorage.authToken); + localStorage.setItem('refreshToken', chromeStorage.refreshToken); + } + return localStorage.getItem('authToken'); + }; + useEffect(() => { const apiUrl = process.env.REACT_APP_CORE_API_URL; // Fetch points and level data when the component mounts const fetchUserData = async () => { + // Add this line to sync tokens before API calls + await syncAuthToken(); + const token = localStorage.getItem('authToken'); if (token) { try { @@ -26,18 +43,17 @@ function WidgetDashboard() { setPoints(response.data.points); setLevel(response.data.level); } - const response_Sparks = await axios.get(`${process.env.REACT_APP_CORE_API_URL}/v2/xp/platform/points/WEBSITE`,{ + const response_Sparks = await axios.get(`${process.env.REACT_APP_CORE_API_URL}/v2/xp/platform/points/WEBSITE`, { headers: { - Authorization: `Bearer ${token}` + Authorization: `Bearer ${token}` } - }); - if(response_Sparks){ - console.log("Sparks data:",response_Sparks.data); - setSparks(response_Sparks.data.user_platform.points); - } - + }); + if (response_Sparks) { + console.log("Widget Sparks data:", response_Sparks.data); + setSparks(response_Sparks.data.user_platform.points); + } } catch (error) { - console.error('Error fetching data:', error); + console.error('Widget Error fetching data:', error); } } }; @@ -61,9 +77,8 @@ function WidgetDashboard() {
3 ? "text-xl" : "text-2xl" - }`} + className={`font-bold ${(points || 0).toString().length > 3 ? "text-xl" : "text-2xl" + }`} style={{ minWidth: "3ch", textAlign: "left" }} > {points || "0"} @@ -71,7 +86,7 @@ function WidgetDashboard() { Hexagon
RelicPoints