mirror of
https://github.com/luxfi/explore.git
synced 2026-09-24 00:28:18 +00:00
fix(footer): follow the brand for the frontend source link
The version link was a module constant naming github.com/luxfi/explore, so every brand's footer sent readers to Lux's repo — explore.hanzo.ai showed "Frontend: v1.1.30" pointing at the Lux org. Brand identity in this image is resolved per host, and the source link now resolves with it: ChainBranding gains sourceUrl (NEXT_PUBLIC_BRAND_SOURCE_URL for external operators, like every other branding field), so Lux keeps its own repo and Hanzo, Zoo, Pars, SPC and Osage each name theirs. Also sets Hanzo's copyright to Hanzo AI, Inc., the entity its terms, privacy, DPA and brand.json all name; Hanzo Industries Inc. predates that consolidation. chainRegistry.spec.ts asserts a brand host surfaces no other org's name or URL in what the footer renders.
This commit is contained in:
@@ -72,6 +72,34 @@ describe('chain-visibility rule', () => {
|
||||
});
|
||||
});
|
||||
|
||||
// The footer renders branding.sourceUrl and branding.orgName verbatim, so a
|
||||
// foreign org in either is a brand leak a reader can see. It shipped once as a
|
||||
// hardcoded github.com/luxfi/explore version link on every brand's footer.
|
||||
describe('a brand host never surfaces another org', () => {
|
||||
const foreign: Record<string, Array<string>> = {
|
||||
'explore.hanzo.ai': [ 'luxfi', 'lux.network', 'zoo', 'pars' ],
|
||||
'explore.hanzo.network': [ 'luxfi', 'lux.network', 'zoo', 'pars' ],
|
||||
'explore.zoo.network': [ 'luxfi', 'lux.network', 'hanzo', 'pars' ],
|
||||
};
|
||||
|
||||
it.each(Object.entries(foreign))('%s footer names only its own org', (host, others) => {
|
||||
atHost(host);
|
||||
const { orgName, sourceUrl, websiteUrl, githubUrl } = getCurrentChain().branding;
|
||||
const rendered = [ orgName, sourceUrl, websiteUrl, githubUrl ].join(' ').toLowerCase();
|
||||
others.forEach((org) => expect(rendered).not.toContain(org));
|
||||
});
|
||||
|
||||
it('lux keeps its own source link', () => {
|
||||
atHost('explore.lux.network');
|
||||
expect(getCurrentChain().branding.sourceUrl).toBe('https://github.com/luxfi/explore');
|
||||
});
|
||||
|
||||
it('hanzo carries the legal entity used across hanzo surfaces', () => {
|
||||
atHost('explore.hanzo.ai');
|
||||
expect(getCurrentChain().branding.orgName).toBe('Hanzo AI, Inc.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('keystone: unregistered white-label hosts are NEVER the primary explorer', () => {
|
||||
it('does not leak the lux primary network to an unknown host', () => {
|
||||
atHost('explore.unknown.example');
|
||||
|
||||
@@ -25,6 +25,11 @@ export interface ChainBranding {
|
||||
/** GitHub org URL */
|
||||
readonly githubUrl: string;
|
||||
|
||||
/** Repository this frontend is built from, for the footer's version link.
|
||||
* Every brand serves the same image from its own org's mirror, so the link
|
||||
* has to follow the brand — a Lux URL on a Hanzo page is a cross-brand leak. */
|
||||
readonly sourceUrl: string;
|
||||
|
||||
/** Twitter/X URL */
|
||||
readonly twitterUrl: string;
|
||||
|
||||
@@ -52,6 +57,7 @@ export function applyBrandEnvOverrides(b: ChainBranding): ChainBranding {
|
||||
websiteUrl: getEnvValue('NEXT_PUBLIC_BRAND_WEBSITE_URL') || b.websiteUrl,
|
||||
description: getEnvValue('NEXT_PUBLIC_BRAND_DESCRIPTION') || b.description,
|
||||
githubUrl: getEnvValue('NEXT_PUBLIC_BRAND_GITHUB_URL') || b.githubUrl,
|
||||
sourceUrl: getEnvValue('NEXT_PUBLIC_BRAND_SOURCE_URL') || b.sourceUrl,
|
||||
twitterUrl: getEnvValue('NEXT_PUBLIC_BRAND_TWITTER_URL') || b.twitterUrl,
|
||||
discordUrl: getEnvValue('NEXT_PUBLIC_BRAND_DISCORD_URL') || b.discordUrl,
|
||||
logoViewBox: getEnvValue('NEXT_PUBLIC_BRAND_LOGO_VIEWBOX') || b.logoViewBox,
|
||||
@@ -105,6 +111,7 @@ const LUX_BRANDING: ChainBranding = {
|
||||
websiteUrl: 'https://lux.network',
|
||||
description: 'High-performance blockchain for decentralized applications.',
|
||||
githubUrl: 'https://github.com/luxfi',
|
||||
sourceUrl: 'https://github.com/luxfi/explore',
|
||||
twitterUrl: 'https://x.com/luxdefi',
|
||||
discordUrl: 'https://discord.gg/luxnetwork',
|
||||
logoViewBox: '0 0 100 100',
|
||||
@@ -120,6 +127,7 @@ const ZOO_BRANDING: ChainBranding = {
|
||||
websiteUrl: 'https://zoo.ngo',
|
||||
description: 'Open AI research network — decentralized AI and science.',
|
||||
githubUrl: 'https://github.com/zoolabs',
|
||||
sourceUrl: 'https://github.com/zooai/explore',
|
||||
twitterUrl: 'https://x.com/zoolabs',
|
||||
discordUrl: 'https://discord.gg/zoolabs',
|
||||
logoViewBox: '0 0 1024 1024',
|
||||
@@ -173,10 +181,11 @@ const ZOO_BRANDING: ChainBranding = {
|
||||
const HANZO_BRANDING: ChainBranding = {
|
||||
brandName: 'Hanzo AI',
|
||||
productName: 'Explorer',
|
||||
orgName: 'Hanzo Industries Inc.',
|
||||
orgName: 'Hanzo AI, Inc.',
|
||||
websiteUrl: 'https://hanzo.ai',
|
||||
description: 'AI blockchain — decentralized compute and inference.',
|
||||
githubUrl: 'https://github.com/hanzoai',
|
||||
sourceUrl: 'https://github.com/hanzoai/explore',
|
||||
twitterUrl: 'https://x.com/hanaboratory',
|
||||
discordUrl: 'https://discord.gg/hanzoai',
|
||||
logoViewBox: '0 0 67 67',
|
||||
@@ -205,6 +214,7 @@ const SPC_BRANDING: ChainBranding = {
|
||||
websiteUrl: 'https://sparkleponyclub.com',
|
||||
description: 'SPC chain.',
|
||||
githubUrl: 'https://github.com/luxfi',
|
||||
sourceUrl: 'https://github.com/luxfi/explore',
|
||||
twitterUrl: 'https://x.com/luxdefi',
|
||||
discordUrl: 'https://discord.gg/luxnetwork',
|
||||
logoViewBox: '0 0 64 64',
|
||||
@@ -223,6 +233,7 @@ const PARS_BRANDING: ChainBranding = {
|
||||
websiteUrl: 'https://pars.network',
|
||||
description: 'Pars blockchain — financial infrastructure for the Persian-speaking world.',
|
||||
githubUrl: 'https://github.com/luxfi',
|
||||
sourceUrl: 'https://github.com/luxfi/explore',
|
||||
twitterUrl: 'https://x.com/parsnetwork',
|
||||
discordUrl: 'https://discord.gg/luxnetwork',
|
||||
logoViewBox: '-120 -120 240 240',
|
||||
@@ -269,6 +280,7 @@ const OSAGE_BRANDING: ChainBranding = {
|
||||
websiteUrl: 'https://osage.network',
|
||||
description: 'Osage blockchain explorer.',
|
||||
githubUrl: 'https://github.com/luxfi',
|
||||
sourceUrl: 'https://github.com/luxfi/explore',
|
||||
twitterUrl: 'https://x.com/luxdefi',
|
||||
discordUrl: 'https://discord.gg/luxnetwork',
|
||||
logoViewBox: '0 0 100 100',
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@luxfi/explore",
|
||||
"version": "1.1.30",
|
||||
"version": "1.1.31",
|
||||
"private": false,
|
||||
"homepage": "https://github.com/luxfi/explore#readme",
|
||||
"engines": {
|
||||
|
||||
@@ -20,9 +20,6 @@ import getApiVersionUrl from './utils/getApiVersionUrl';
|
||||
|
||||
const MAX_LINKS_COLUMNS = 4;
|
||||
|
||||
const FRONT_VERSION_URL = `https://github.com/luxfi/explore/tree/${ config.UI.footer.frontendVersion }`;
|
||||
const FRONT_COMMIT_URL = `https://github.com/luxfi/explore/commit/${ config.UI.footer.frontendCommit }`;
|
||||
|
||||
const Footer = () => {
|
||||
|
||||
const { data: backendVersionData } = useApiQuery('general:config_backend_version', {
|
||||
@@ -73,11 +70,13 @@ const Footer = () => {
|
||||
|
||||
const frontendLink = (() => {
|
||||
if (config.UI.footer.frontendVersion) {
|
||||
return <Link href={ FRONT_VERSION_URL } external noIcon>{ config.UI.footer.frontendVersion }</Link>;
|
||||
const href = `${ branding.sourceUrl }/tree/${ config.UI.footer.frontendVersion }`;
|
||||
return <Link href={ href } external noIcon>{ config.UI.footer.frontendVersion }</Link>;
|
||||
}
|
||||
|
||||
if (config.UI.footer.frontendCommit) {
|
||||
return <Link href={ FRONT_COMMIT_URL } external noIcon>{ config.UI.footer.frontendCommit }</Link>;
|
||||
const href = `${ branding.sourceUrl }/commit/${ config.UI.footer.frontendCommit }`;
|
||||
return <Link href={ href } external noIcon>{ config.UI.footer.frontendCommit }</Link>;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user