Skip to content

Commit 2b05dc2

Browse files
sammdecclaude
andcommitted
feat: add link to Avalanche V4 instance in market switcher
Adds an "Avalanche" entry with a V4 pill to the L1 Networks section of the market switcher, linking out to pro.aave.com. Generalises the hardcoded Aave Pro link into a V4_LINKS list plus a single renderV4Link helper, so V4 instances are one line of config each. Also fixes the search box for these rows: they were rendered outside the query filter, so searching "prime" showed Aave Pro while searching "aave pro" hid the whole Ethereum section and made it unreachable. V4 links are now filtered by the same query as real markets, and count towards the no-results check. Clicks fire DASHBOARD.CHANGE_MARKET so V4 referral traffic is measurable; previously the Aave Pro link tracked nothing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 7e5bb41 commit 2b05dc2

6 files changed

Lines changed: 61 additions & 22 deletions

File tree

src/components/MarketSwitcher.tsx

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,32 @@ const getMarketOrder = (marketId: CustomMarket): number => {
184184
};
185185

186186
const AAVE_PRO_URL = 'https://pro.aave.com/';
187-
const AAVE_PRO_LOGO = '/icons/markets/aave-pro.png';
187+
188+
type V4Link = {
189+
id: string;
190+
label: string;
191+
logo: string;
192+
url: string;
193+
section: Extract<MarketCategory, 'ethereum' | 'other'>;
194+
};
195+
196+
// External links to V4 instances, rendered alongside the V3 markets of the same section.
197+
const V4_LINKS: V4Link[] = [
198+
{
199+
id: 'aave_pro_v4',
200+
label: 'Aave Pro',
201+
logo: '/icons/markets/aave-pro.png',
202+
url: AAVE_PRO_URL,
203+
section: 'ethereum',
204+
},
205+
{
206+
id: 'aave_pro_avalanche_v4',
207+
label: 'Avalanche',
208+
logo: '/icons/networks/avalanche.svg',
209+
url: AAVE_PRO_URL,
210+
section: 'other',
211+
},
212+
];
188213

189214
export const MarketSwitcher = () => {
190215
const [anchorEl, setAnchorEl] = useState<HTMLElement | null>(null);
@@ -249,7 +274,7 @@ export const MarketSwitcher = () => {
249274
// Filter to V3 markets only
250275
const v3Markets = useMemo(() => availableMarkets.filter((id) => marketsData[id].v3), []);
251276

252-
const { pinned, ethereum, l2, other, legacy } = useMemo(() => {
277+
const { pinned, ethereum, l2, other, legacy, v4Ethereum, v4Other } = useMemo(() => {
253278
const query = searchQuery.toLowerCase();
254279
const filtered = v3Markets.filter((id) => {
255280
const { market } = getMarketInfoById(id);
@@ -261,12 +286,16 @@ export const MarketSwitcher = () => {
261286
const pinnedSet = new Set(pinned);
262287
const unpinned = sorted.filter((id) => !pinnedSet.has(id));
263288

289+
const v4Links = V4_LINKS.filter((link) => link.label.toLowerCase().includes(query));
290+
264291
return {
265292
pinned,
266293
ethereum: unpinned.filter((id) => getMarketCategory(id) === 'ethereum'),
267294
l2: unpinned.filter((id) => getMarketCategory(id) === 'l2'),
268295
other: unpinned.filter((id) => getMarketCategory(id) === 'other'),
269296
legacy: unpinned.filter((id) => getMarketCategory(id) === 'legacy'),
297+
v4Ethereum: v4Links.filter((link) => link.section === 'ethereum'),
298+
v4Other: v4Links.filter((link) => link.section === 'other'),
270299
};
271300
}, [v3Markets, searchQuery, favoriteMarkets, isFavoriteMarket]);
272301

@@ -424,15 +453,22 @@ export const MarketSwitcher = () => {
424453
);
425454
};
426455

427-
const renderAaveProLink = (isMobile?: boolean, width = '33.33%') => (
456+
const handleSelectV4Link = (link: V4Link) => {
457+
trackEvent(DASHBOARD.CHANGE_MARKET, { market: link.id });
458+
window.open(link.url, '_blank');
459+
};
460+
461+
const renderV4Link = (link: V4Link, isMobile?: boolean, width = '33.33%') => (
428462
<Box
463+
key={link.id}
429464
role="button"
430465
tabIndex={0}
431-
onClick={() => window.open(AAVE_PRO_URL, '_blank')}
466+
data-cy={`marketSelector_${link.id}`}
467+
onClick={() => handleSelectV4Link(link)}
432468
onKeyDown={(e: React.KeyboardEvent) => {
433469
if (e.key === 'Enter' || e.key === ' ') {
434470
e.preventDefault();
435-
window.open(AAVE_PRO_URL, '_blank');
471+
handleSelectV4Link(link);
436472
}
437473
}}
438474
sx={{
@@ -449,7 +485,7 @@ export const MarketSwitcher = () => {
449485
>
450486
<Box sx={{ width: 20, height: 20, mr: 1, flexShrink: 0 }}>
451487
<img
452-
src={AAVE_PRO_LOGO}
488+
src={link.logo}
453489
alt=""
454490
width="100%"
455491
height="100%"
@@ -475,7 +511,7 @@ export const MarketSwitcher = () => {
475511
lineHeight: '20px',
476512
}}
477513
>
478-
<Trans>Aave Pro</Trans>
514+
{link.label}
479515
</Typography>
480516
<Box
481517
component="span"
@@ -520,7 +556,12 @@ export const MarketSwitcher = () => {
520556
);
521557

522558
const noResults =
523-
pinned.length === 0 && ethereum.length === 0 && l2.length === 0 && other.length === 0;
559+
pinned.length === 0 &&
560+
ethereum.length === 0 &&
561+
l2.length === 0 &&
562+
other.length === 0 &&
563+
v4Ethereum.length === 0 &&
564+
v4Other.length === 0;
524565

525566
const renderSelectorContent = (mobile: boolean) => (
526567
<>
@@ -609,25 +650,27 @@ export const MarketSwitcher = () => {
609650
)}
610651

611652
{/* Ethereum */}
612-
{ethereum.length > 0 && (
653+
{(ethereum.length > 0 || v4Ethereum.length > 0) && (
613654
<Box>
614655
{sectionHeader(<Trans>Ethereum</Trans>)}
615656
<Box sx={{ display: 'flex', flexWrap: 'wrap', px: 1.5 }}>
616657
{ethereum.map((id) => renderGridItem(id, mobile, '33%'))}
617-
{renderAaveProLink(mobile, '33%')}
658+
{v4Ethereum.map((link) => renderV4Link(link, mobile, '33%'))}
618659
</Box>
619-
{(other.length > 0 || l2.length > 0 || (showLegacy && legacy.length > 0)) && (
620-
<Divider sx={{ my: 1 }} />
621-
)}
660+
{(other.length > 0 ||
661+
v4Other.length > 0 ||
662+
l2.length > 0 ||
663+
(showLegacy && legacy.length > 0)) && <Divider sx={{ my: 1 }} />}
622664
</Box>
623665
)}
624666

625667
{/* L1 Networks */}
626-
{other.length > 0 && (
668+
{(other.length > 0 || v4Other.length > 0) && (
627669
<Box>
628670
{sectionHeader(<Trans>L1 Networks</Trans>)}
629671
<Box sx={{ display: 'flex', flexWrap: 'wrap', px: 1.5 }}>
630672
{other.map((id) => renderGridItem(id, mobile))}
673+
{v4Other.map((link) => renderV4Link(link, mobile))}
631674
</Box>
632675
{(l2.length > 0 || showLegacy) && <Divider sx={{ my: 1 }} />}
633676
</Box>

src/locales/el/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/messages.po

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -621,10 +621,6 @@ msgstr "Time remaining until the withdraw period ends."
621621
msgid "Withdrawing and Swapping"
622622
msgstr "Withdrawing and Swapping"
623623

624-
#: src/components/MarketSwitcher.tsx
625-
msgid "Aave Pro"
626-
msgstr "Aave Pro"
627-
628624
#: src/modules/reserve-overview/graphs/MeritApyGraphContainer.tsx
629625
msgid "Data couldn't be fetched, please reload graph."
630626
msgstr "Data couldn't be fetched, please reload graph."

src/locales/es/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/fr/messages.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)