Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 54 additions & 10 deletions components/Treasury/TreasuryVoteTable/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,59 @@ import TreasuryVotePopover from "./TreasuryVotePopover";
import { DesktopVoteTable, Vote } from "./Views/DesktopVoteTable";
import { MobileVoteCards } from "./Views/MobileVoteTable";

// Module-level cache to avoid repeated ENS lookups across renders/navigations.
// Bound size keeps memory usage predictable during long sessions.
const ENS_CACHE_MAX_ENTRIES = 2000;
const ensCache = new Map<string, string>();
const ensLookupInFlight = new Map<string, Promise<string>>();

const getCachedEns = (address: string) => {
if (!ensCache.has(address)) return undefined;
const cached = ensCache.get(address)!;

Comment thread
ECWireless marked this conversation as resolved.
// Refresh insertion order so frequently used addresses stay cached.
ensCache.delete(address);
ensCache.set(address, cached);

return cached;
};

const setCachedEns = (address: string, ensName: string) => {
if (ensCache.has(address)) {
ensCache.delete(address);
}
ensCache.set(address, ensName);

if (ensCache.size > ENS_CACHE_MAX_ENTRIES) {
const oldestKey = ensCache.keys().next().value;
if (oldestKey !== undefined) {
ensCache.delete(oldestKey);
}
}
};

Comment thread
vercel[bot] marked this conversation as resolved.
const resolveEnsName = (address: string): Promise<string> => {
const cacheKey = address.toLowerCase();
const cached = getCachedEns(cacheKey);
if (cached) return Promise.resolve(cached);

const inFlightLookup = ensLookupInFlight.get(cacheKey);
if (inFlightLookup) return inFlightLookup;

const lookupPromise = getEnsForVotes(address)
.then((ensAddress) => {
const ensName = ensAddress?.name || formatAddress(address);
setCachedEns(cacheKey, ensName);
return ensName;
})
.finally(() => {
ensLookupInFlight.delete(cacheKey);
});

ensLookupInFlight.set(cacheKey, lookupPromise);
return lookupPromise;
};

interface TreasuryVoteTableProps {
proposalId: string;
}
Expand Down Expand Up @@ -59,16 +112,7 @@ const useVotes = (proposalId: string) => {
await Promise.all(
uniqueVoters.map(async (address) => {
try {
if (localEnsCache[address]) {
return;
}
const ensAddress = await getEnsForVotes(address);

if (ensAddress && ensAddress.name) {
localEnsCache[address] = ensAddress.name;
} else {
localEnsCache[address] = formatAddress(address);
}
localEnsCache[address] = await resolveEnsName(address);
} catch (e) {
console.warn(`Failed to fetch ENS for ${address}`, e);
}
Expand Down