Skip to content
Merged
Show file tree
Hide file tree
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
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,7 @@ src/globalTypes.ts
.env
dist

stats.html
stats.html

.yarn
.data
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
54 changes: 52 additions & 2 deletions src/components/ProjectCard/ProjectCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0

import * as React from 'react';
import { IndexerName } from '@components/IndexerDetails/IndexerName';
import { Manifest } from '@hooks/useGetDeploymentManifest';
import { Address, Typography } from '@subql/components';
import { ProjectFieldsFragment, ProjectType } from '@subql/network-query';
Expand All @@ -12,6 +11,7 @@ import BigNumber from 'bignumber.js';
import dayjs from 'dayjs';
import { toSvg } from 'jdenticon';

import { getNetworkNameByChainId } from 'src/const/const';
import { ProjectMetadata } from 'src/models';

import IPFSImage from '../IPFSImage';
Expand All @@ -26,6 +26,8 @@ type Props = {
};

const { PROJECT_NAV } = ROUTES;
const MAX_NETWORK_NAME_LENGTH = 28;
const MAX_CHAIN_ID_LENGTH = 18;

const ProjectCard: React.FC<Props> = ({ project, href, onClick }) => {
const ipfsImage = React.useMemo(() => {
Expand All @@ -49,6 +51,41 @@ const ProjectCard: React.FC<Props> = ({ project, href, onClick }) => {
);
}, [project?.deployments?.nodes]);

const networkVal = React.useMemo(() => {
if (project.type === ProjectType.RPC && project.manifest?.rpcFamily) {
return project.manifest.rpcFamily[0];
}

const chainId =
project.type === ProjectType.SUBQUERY
? project.manifest?.network?.chainId
: project.manifest?.dataSources?.[0]?.network;
if (!chainId) return '-';

return (
getNetworkNameByChainId(chainId, {
projectName: project.metadata?.name,
projectId: project.id,
source: 'ProjectCard',
}) || `Chain ID ${chainId}`
);
}, [project.type, project.manifest, project.id, project.metadata?.name]);

const isChainIdFallback = React.useMemo(() => {
return `${networkVal || '-'}`.startsWith('Chain ID ');
}, [networkVal]);

const chainIdDisplayVal = React.useMemo(() => {
if (!isChainIdFallback) return '';
const val = `${networkVal || '-'}`.replace('Chain ID ', '');
return val.length > MAX_CHAIN_ID_LENGTH ? `${val.slice(0, MAX_CHAIN_ID_LENGTH)}...` : val;
}, [isChainIdFallback, networkVal]);

const networkDisplayVal = React.useMemo(() => {
const val = `${networkVal || '-'}`;
return val.length > MAX_NETWORK_NAME_LENGTH ? `${val.slice(0, MAX_NETWORK_NAME_LENGTH)}...` : val;
}, [networkVal]);

return (
<a
href={href ? href : `${PROJECT_NAV}/${project.id}`}
Expand Down Expand Up @@ -76,7 +113,20 @@ const ProjectCard: React.FC<Props> = ({ project, href, onClick }) => {
</div>

{project.type === ProjectType.SUBQUERY || project.type === ProjectType.SUBGRAPH ? (
<IndexerName address={project.owner} size="tiny" />
<div className="flex">
{isChainIdFallback ? (
<>
<Typography variant="small" type="secondary">
Chain ID
</Typography>
<Typography variant="small" style={{ marginLeft: 6 }}>
{chainIdDisplayVal}
</Typography>
</>
) : (
<Typography variant="small">{networkDisplayVal}</Typography>
)}
</div>
) : (
<Typography variant="small" style={{ textTransform: 'uppercase' }}>
{project.manifest?.rpcFamily?.[0]}
Expand Down
15 changes: 9 additions & 6 deletions src/components/ProjectHeader/ProjectHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import clsx from 'clsx';
import dayjs from 'dayjs';
import { toSvg } from 'jdenticon';

import { ETH_TYPE_DICTION, NETWORK_TYPE_DICTION } from 'src/const/const';
import { getNetworkNameByChainId } from 'src/const/const';
import { useProjectStore } from 'src/stores/project';

import Detail from '../Detail';
Expand Down Expand Up @@ -104,11 +104,14 @@ const ProjectHeader: React.FC<Props> = ({
project.type === ProjectType.SUBQUERY ? manifest?.network?.chainId : manifest?.dataSources?.[0]?.network;
if (!chainId) return '-';

const polkadotName = NETWORK_TYPE_DICTION[chainId];
const ethName = ETH_TYPE_DICTION[chainId];

return polkadotName || ethName || chainId;
}, [project.type, manifest]);
return (
getNetworkNameByChainId(chainId, {
projectName: project.metadata?.name,
projectId: project.id,
source: 'ProjectHeader',
}) || chainId
);
}, [project.type, manifest, project.id, project.metadata?.name]);

const isOnwer = React.useMemo(() => account === project.owner, [project.owner, account]);

Expand Down
69 changes: 69 additions & 0 deletions src/const/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@ export const NETWORK_TYPE_DICTION: { [key in string]: string } = {
'0xa85cfb9b9fd4d622a5b28289a02347af987d8f73fa3108450e2b4a11c1ce5755': 'Basilisk',
'0xaa3876c1dc8a1afcc2e9a685a49ff7704cfd36ad8c90bf2702b9d1b00cc40011': 'Altair',
'0x1bb969d85965e4bb5a651abbedf21a54b6b31a21f66b5401cc3f1e286268d736': 'Phala',
'0x4a12be580bb959937a1c7a61d5cf24428ed67fa571974b4007645d1886e7c89f': 'Subsocial',
'4221332d34e1694168c2a0c0b3fd0f273809612cb13d000d5c2e00e85f50f796': 'Concordium Testnet',
'9dd9ca4d19e9393877d2c44b70f89acbfc0883c2243e5eeaecc0d1cd0503f478': 'Concordium Mainnet',
'5eykt4UsFv8P8NJdTREpY1vzqKqZKvdpKuc147dw2N9d': 'Solana Mainnet',
EtWTRABZaYq6iMfeYKouRu166VU2xqa1wcaWoxPkrZBG: 'Solana Devnet',
'4uhcVJyU9pJkvQyS88uRDiswHXSCkY3zQawwpjk2NsNY': 'Solana Testnet',
'fetchhub-4': 'Fetch.ai Mainnet',
'juno-1': 'Juno Mainnet',
'near-testnet': 'NEAR Testnet',
mainnet: 'NEAR Mainnet',
'axelar-dojo-1': 'Axelar Dojo',
'telos-testnet': 'Telos Testnet',
'coti-mainnet': 'COTI Mainnet',
flare: 'Flare',
'Public Global Stellar Network ; September 2015': 'Stellar Mainnet',
'Test SDF Network ; September 2015': 'Stellar Testnet',
};

export const ETH_TYPE_DICTION: { [key in string]: string } = {
Expand Down Expand Up @@ -971,4 +987,57 @@ export const ETH_TYPE_DICTION: { [key in string]: string } = {
'666301171999': 'PDC Mainnet',
'6022140761023': 'Molereum Network',
'2716446429837000': 'DCHAIN',
'97': 'BNB Smart Chain Testnet',
'232': 'Lens',
'999': 'HyperEVM',
'2741': 'Abstract',
'4158': 'CrossFi Mainnet',
'6900': 'Nibiru cataclysm-1',
'48900': 'Zircuit Mainnet',
'102031': 'Creditcoin Testnet',
'421614': 'Arbitrum Sepolia',
'84532': 'Base Sepolia',
'11155111': 'Ethereum Sepolia',
'65000000': 'Autonity Mainnet',
'10200': 'Gnosis Chiado Testnet',
gnosis: 'Gnosis',
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Inconsistent key format: gnosis is not a numeric chain ID.

All other entries in ETH_TYPE_DICTION use numeric chain IDs as string keys (e.g., '100' for Gnosis). The key gnosis won't match lookups using the actual chain ID '100'. This appears to be a duplicate or erroneous entry since '100': 'Gnosis' already exists at line 119.

Suggested fix: remove duplicate entry
   '10200': 'Gnosis Chiado Testnet',
-  gnosis: 'Gnosis',
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
gnosis: 'Gnosis',
'10200': 'Gnosis Chiado Testnet',
};
🤖 Prompt for AI Agents
In `@src/const/const.ts` at line 1003, ETH_TYPE_DICTION contains an inconsistent
duplicate key "gnosis" (string name) while the rest use numeric chain ID strings
(e.g., "100": "Gnosis"); remove the erroneous "gnosis": "Gnosis" entry from
ETH_TYPE_DICTION (or if intended, replace the key with "100") so lookups using
the numeric chain ID match the correct value.

};

const missingNetworkChainIdSet = new Set<string>();
const missingNetworkChainIdWithProjectSet = new Set<string>();

type NetworkNameContext = {
projectName?: string;
projectId?: string;
source?: string;
};

export const getNetworkNameByChainId = (chainId?: string, context?: NetworkNameContext): string | undefined => {
if (!chainId) return undefined;

const networkName = NETWORK_TYPE_DICTION[chainId] || ETH_TYPE_DICTION[chainId];

// Temporary debug: collect unmapped chain IDs while browsing pages locally.
if (!networkName && import.meta.env.DEV) {
const projectName = context?.projectName || 'unknown';
const projectId = context?.projectId || 'unknown';
const source = context?.source || 'unknown';
const missingKey = `${chainId}::${projectId}::${source}`;

if (missingNetworkChainIdWithProjectSet.has(missingKey)) {
return networkName;
}

missingNetworkChainIdWithProjectSet.add(missingKey);
missingNetworkChainIdSet.add(chainId);

(globalThis as { __missingNetworkChainIds?: string[] }).__missingNetworkChainIds =
Array.from(missingNetworkChainIdSet);

console.warn(
`[NetworkMap] Missing chain id mapping: ${chainId} | project: ${projectName} (${projectId}) | source: ${source}`,
);
}

return networkName;
};
2 changes: 1 addition & 1 deletion src/hooks/useProjectList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const ProjectItem: React.FC<{
onClick?: () => void;
}> = ({ project, makeRedirectHref, onClick }) => {
const { getMetadataFromCid } = useProjectMetadata();
const { manifest } = useGetDeploymentManifest(project.type === ProjectType.RPC ? project.deploymentId : '');
const { manifest } = useGetDeploymentManifest(project.deploymentId);

const { data: metadata } = useAsyncMemo(() => getMetadataFromCid(project.metadata), [project]);

Expand Down
Loading
Loading