diff --git a/src/app/api/chains/[family]/addresses/[address]/balance/route.ts b/src/app/api/chains/[family]/addresses/[address]/balance/route.ts index 33abf9d..76a4c87 100644 --- a/src/app/api/chains/[family]/addresses/[address]/balance/route.ts +++ b/src/app/api/chains/[family]/addresses/[address]/balance/route.ts @@ -11,7 +11,9 @@ import { throwIfQueryParamIsNull } from "../../../../../utils/throwIfQueryParamI // cache balance for 5 seconds const headers = { headers: { - "Cache-Control": `public, max-age=${5}`, + "Cache-Control": "public, s-maxage=5", + "CDN-Cache-Control": "public, s-maxage=5", + "Vercel-CDN-Cache-Control": "public, s-maxage=5", }, } export async function GET( diff --git a/src/hooks/useTokenBalances/stores/amountsStore.ts b/src/hooks/useTokenBalances/stores/amountsStore.ts index dda7471..30301e8 100644 --- a/src/hooks/useTokenBalances/stores/amountsStore.ts +++ b/src/hooks/useTokenBalances/stores/amountsStore.ts @@ -10,6 +10,7 @@ import type { Tokens } from "@/tokens/types" import type { NormalizedAddressMap } from "../NormalizedAddressMap" import { focusStore } from "./focusStore" +import { inactivityStore } from "./inactivityStore" import { tokensStore } from "./tokensStore" const AMOUNTS_REFRESH_INTERVAL_MS = 1000 * 60 * 3 @@ -99,7 +100,8 @@ subscribeKey(sessionState, "addresses", (addresses) => { setInterval(() => { const now = Date.now() - if (!focusStore.isWalletInFocus) { + // Skip if not focused OR inactive + if (!focusStore.isWalletInFocus || !inactivityStore.isActive) { return } diff --git a/src/hooks/useTokenBalances/stores/inactivityStore.ts b/src/hooks/useTokenBalances/stores/inactivityStore.ts new file mode 100644 index 0000000..30f999a --- /dev/null +++ b/src/hooks/useTokenBalances/stores/inactivityStore.ts @@ -0,0 +1,54 @@ +import { proxy } from "valtio" + +type InactivityStore = { + isActive: boolean + lastInteractionTime: number + inactivityTimeoutMs: number +} + +export const inactivityStore = proxy({ + isActive: true, + lastInteractionTime: Date.now(), + inactivityTimeoutMs: 1000 * 60 * 5, // 5 minutes +}) + +const updateInactivityStore = () => { + const resetInactivity = () => { + inactivityStore.lastInteractionTime = Date.now() + inactivityStore.isActive = true + } + + if (typeof window === "undefined") { + return () => {} + } + + // Track user interactions + const events = [ + "mousemove", + "keydown", + "click", + "touchstart", + "scroll", + "wheel", + ] + events.forEach((event) => { + window.addEventListener(event, resetInactivity, { passive: true }) + }) + + // Check inactivity every 10 seconds + const inactivityCheckInterval = setInterval(() => { + const timeSinceLastInteraction = + Date.now() - inactivityStore.lastInteractionTime + inactivityStore.isActive = + timeSinceLastInteraction < inactivityStore.inactivityTimeoutMs + }, 10_000) + + return () => { + events.forEach((event) => { + window.removeEventListener(event, resetInactivity) + }) + clearInterval(inactivityCheckInterval) + } +} + +updateInactivityStore() diff --git a/src/hooks/useTokenBalances/stores/tokensStore.ts b/src/hooks/useTokenBalances/stores/tokensStore.ts index ad97a23..de59e4f 100644 --- a/src/hooks/useTokenBalances/stores/tokensStore.ts +++ b/src/hooks/useTokenBalances/stores/tokensStore.ts @@ -1,10 +1,14 @@ import { proxy } from "valtio" +import { subscribeKey } from "valtio/utils" import type { Tokens } from "@/tokens/types" import { getTokens } from "../fetchers/tokens" +import { focusStore } from "./focusStore" +import { inactivityStore } from "./inactivityStore" const TOKENS_REFRESH_INTERVAL_MS = 1000 * 60 * 60 +let nextRefreshAt = Date.now() + TOKENS_REFRESH_INTERVAL_MS type TokensStore = { tokens: Tokens | undefined @@ -37,4 +41,18 @@ export const tokensStore = proxy({ }) refreshTokens() -setInterval(refreshTokens, TOKENS_REFRESH_INTERVAL_MS) +const refreshTokensIfDue = () => { + if (!focusStore.isWalletInFocus || !inactivityStore.isActive) { + return + } + + const now = Date.now() + if (now < nextRefreshAt) return + + nextRefreshAt = now + TOKENS_REFRESH_INTERVAL_MS + refreshTokens() +} + +setInterval(refreshTokensIfDue, TOKENS_REFRESH_INTERVAL_MS) +subscribeKey(focusStore, "isWalletInFocus", refreshTokensIfDue) +subscribeKey(inactivityStore, "isActive", refreshTokensIfDue)