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

stats.html
stats.html

.yarn
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
51 changes: 49 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 { ETH_TYPE_DICTION, NETWORK_TYPE_DICTION } 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,38 @@ 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 '-';

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

return polkadotName || ethName || `Chain ID ${chainId}`;
}, [project.type, project.manifest]);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Edge case: empty rpcFamily array returns undefined.

If rpcFamily is an empty array [], the condition on line 55 evaluates to truthy, and rpcFamily[0] returns undefined. While downstream code handles this via ${networkVal || '-'} fallback, explicitly checking array length would make the intent clearer.

Suggested improvement
   const networkVal = React.useMemo(() => {
-    if (project.type === ProjectType.RPC && project.manifest?.rpcFamily) {
+    if (project.type === ProjectType.RPC && project.manifest?.rpcFamily?.length) {
       return project.manifest.rpcFamily[0];
     }
📝 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
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 '-';
const polkadotName = NETWORK_TYPE_DICTION[chainId];
const ethName = ETH_TYPE_DICTION[chainId];
return polkadotName || ethName || `Chain ID ${chainId}`;
}, [project.type, project.manifest]);
const networkVal = React.useMemo(() => {
if (project.type === ProjectType.RPC && project.manifest?.rpcFamily?.length) {
return project.manifest.rpcFamily[0];
}
const chainId =
project.type === ProjectType.SUBQUERY
? project.manifest?.network?.chainId
: project.manifest?.dataSources?.[0]?.network;
if (!chainId) return '-';
const polkadotName = NETWORK_TYPE_DICTION[chainId];
const ethName = ETH_TYPE_DICTION[chainId];
return polkadotName || ethName || `Chain ID ${chainId}`;
}, [project.type, project.manifest]);
🤖 Prompt for AI Agents
In `@src/components/ProjectCard/ProjectCard.tsx` around lines 54 - 69, In
ProjectCard's networkVal useMemo the RPC branch returns
project.manifest.rpcFamily[0] without checking length, which yields undefined
for an empty array; update the RPC branch in networkVal (used in ProjectCard
when project.type === ProjectType.RPC) to check that
project.manifest?.rpcFamily?.length > 0 and return the first element only then,
otherwise fall back to '-' (or the existing downstream fallback), ensuring
project.manifest.rpcFamily is safely handled.


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 +110,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
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