diff --git a/package.json b/package.json
index 25d9ed648..0191dc23b 100644
--- a/package.json
+++ b/package.json
@@ -24,8 +24,8 @@
"@subql/contract-sdk": "0.112.0",
"@subql/network-clients": "^0.112.1-1",
"@subql/network-config": "^0.112.0",
- "@subql/network-query": "0.112.1-0",
- "@subql/react-hooks": "^0.112.1-2",
+ "@subql/network-query": "0.112.1-1",
+ "@subql/react-hooks": "^0.112.1-3",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx
index 5cdf84d93..2c93dc564 100644
--- a/src/components/Header/Header.tsx
+++ b/src/components/Header/Header.tsx
@@ -37,17 +37,6 @@ export interface AppNavigation {
export const Header: React.FC = () => {
const { address: account } = useAccount();
const navigate = useNavigate();
- const calEntryLinks = React.useMemo(() => {
- return entryLinks.map((entry) => {
- if (entry.key === 'explorer') {
- return {
- ...entry,
- dropdown: undefined,
- };
- }
- return entry;
- });
- }, []);
return (
@@ -55,7 +44,7 @@ export const Header: React.FC = () => {
navigate={(link) => {
navigate(link);
}}
- appNavigation={calEntryLinks}
+ appNavigation={entryLinks}
dropdownLinks={{ label: 'Kepler', links: externalAppLinks }}
rightElement={
<>
diff --git a/src/components/IndexerDetails/IndexerDetails.module.less b/src/components/IndexerDetails/IndexerDetails.module.less
index e9d9f73a9..a4fd443c1 100644
--- a/src/components/IndexerDetails/IndexerDetails.module.less
+++ b/src/components/IndexerDetails/IndexerDetails.module.less
@@ -170,6 +170,8 @@
color: #fff;
font-size: 18px;
margin-bottom: 8px;
+ display: flex;
+ align-items: center;
}
&LimitInfo {
diff --git a/src/components/IndexerDetails/IndexerDetails.tsx b/src/components/IndexerDetails/IndexerDetails.tsx
index 87ce54705..5fc6683af 100644
--- a/src/components/IndexerDetails/IndexerDetails.tsx
+++ b/src/components/IndexerDetails/IndexerDetails.tsx
@@ -4,6 +4,7 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { EmptyList } from '@components/EmptyList';
+import { ProjectDetailsQuery } from '@hooks/useProjectFromQuery';
import { Spinner, TableTitle, Typography } from '@subql/components';
import { ServiceStatus } from '@subql/network-query';
import { renderAsync, useGetDeploymentIndexersLazyQuery, useGetIndexerDeploymentLazyQuery } from '@subql/react-hooks';
@@ -16,6 +17,7 @@ import Row from './Row';
type Props = {
deploymentId: string | undefined;
+ project: ProjectDetailsQuery;
};
const NoIndexers: React.FC = () => {
@@ -31,7 +33,7 @@ const NoIndexers: React.FC = () => {
);
};
-const IndexerDetails: React.FC
= ({ deploymentId }) => {
+const IndexerDetails: React.FC = ({ deploymentId, project }) => {
const { t } = useTranslation();
const [loadIndexersLazy, asyncIndexers] = useGetDeploymentIndexersLazyQuery();
@@ -156,7 +158,7 @@ const IndexerDetails: React.FC = ({ deploymentId }) => {
.filter(notEmpty)
.sort((indexer) => (indexer.status === ServiceStatus.READY ? -1 : 1))
.map((indexer) => (
-
+
))}
>
diff --git a/src/components/IndexerDetails/Row.tsx b/src/components/IndexerDetails/Row.tsx
index 1ed089111..c3cbf24ff 100644
--- a/src/components/IndexerDetails/Row.tsx
+++ b/src/components/IndexerDetails/Row.tsx
@@ -6,6 +6,7 @@ import { useTranslation } from 'react-i18next';
import { BsChevronDown, BsChevronUp, BsInfoSquare } from 'react-icons/bs';
import { useNavigate } from 'react-router';
import { LazyQueryResult } from '@apollo/client';
+import RpcPlayground from '@components/RpcPlayground/RpcPlayground';
import { WalletRoute } from '@components/WalletRoute';
import { useIsLogin } from '@hooks/useIsLogin';
import { useRequestServiceAgreementToken } from '@hooks/useRequestServiceAgreementToken';
@@ -14,6 +15,7 @@ import { GraphiQL } from '@subql/components/dist/common/GraphiQL';
import {
GetDeploymentIndexersQuery,
PlansNodeFieldsFragment as Plan,
+ ProjectType,
ServiceStatus as DeploymentStatus,
} from '@subql/network-query';
import { useGetDeploymentPlansLazyQuery } from '@subql/react-hooks';
@@ -25,6 +27,7 @@ import clsx from 'clsx';
import { t } from 'i18next';
import { useAccount } from 'wagmi';
+import RpcPlaygroundIcon from 'src/images/rpcPlayground';
import { useWeb3Store } from 'src/stores';
import { useProjectStore } from 'src/stores/project';
@@ -77,7 +80,8 @@ export interface QueryLimit {
const ConnectedRow: React.FC<{
indexer: ExcludeNull
['nodes'][number]>;
deploymentId?: string;
-}> = ({ indexer, deploymentId }) => {
+ type: ProjectType;
+}> = ({ indexer, deploymentId, type }) => {
const { t } = useTranslation();
const { address: account } = useAccount();
const navigate = useNavigate();
@@ -175,7 +179,6 @@ const ConnectedRow: React.FC<{
>
),
},
-
{
width: '13%',
render: () => {
@@ -211,7 +214,16 @@ const ConnectedRow: React.FC<{
setShowReqTokenConfirmModal(true);
}}
>
-
+ {type === ProjectType.SUBQUERY ? (
+
+ ) : (
+
+ )}
Playground
);
@@ -332,7 +344,13 @@ const ConnectedRow: React.FC<{
>
{t('explorer.flexPlans.requestToken')}}
+ element={
+
+ {t('explorer.flexPlans.requestToken', {
+ type: type === ProjectType.RPC ? 'JSON' : 'Graphql',
+ })}
+
+ }
>
@@ -344,7 +362,11 @@ const ConnectedRow: React.FC<{
>
-
+ {type === ProjectType.SUBQUERY ? (
+
+ ) : (
+
+ )}
{t('myFlexPlans.playground')}
@@ -361,7 +383,10 @@ const ConnectedRow: React.FC<{
- {queryUrl && trailToken && }
+ {type === ProjectType.SUBQUERY && queryUrl && trailToken && (
+
+ )}
+ {type === ProjectType.RPC && }
>
);
diff --git a/src/components/ProjectHeader/ProjectHeader.tsx b/src/components/ProjectHeader/ProjectHeader.tsx
index 25cc62b09..f6ee18363 100644
--- a/src/components/ProjectHeader/ProjectHeader.tsx
+++ b/src/components/ProjectHeader/ProjectHeader.tsx
@@ -71,9 +71,10 @@ const ProjectHeader: React.FC = ({
{isUnsafeDeployment && }
-
+ {/* TODO: finish this */}
+ {/*
Get RPC Endpoint
-
+ */}
diff --git a/src/components/RpcPlayground/RpcPlayground.tsx b/src/components/RpcPlayground/RpcPlayground.tsx
new file mode 100644
index 000000000..ac353c132
--- /dev/null
+++ b/src/components/RpcPlayground/RpcPlayground.tsx
@@ -0,0 +1,98 @@
+// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+import React, { FC, useMemo, useState } from 'react';
+import { Typography } from '@subql/components';
+import { getAuthReqHeader } from '@utils';
+import { Button, Input } from 'antd';
+import { fetchJson } from 'ethers/lib/utils';
+
+import styles from './index.module.less';
+
+interface IProps {
+ url?: string;
+ trailToken: string;
+}
+
+const RpcPlayground: FC = ({ url, trailToken }) => {
+ const [val, setVal] = useState('');
+ const [loading, setLoading] = useState(false);
+ const enteredRows = useMemo(() => {
+ return val.split('\n').length;
+ }, [val]);
+
+ const [responseData, setResponseData] = useState('');
+
+ const fetchRpc = async () => {
+ if (!url) return;
+ try {
+ setLoading(true);
+ const res = await fetchJson(
+ {
+ url,
+ headers: {
+ ...getAuthReqHeader(trailToken),
+ },
+ },
+ val,
+ );
+
+ setResponseData(JSON.stringify(res));
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ } catch (e: any) {
+ setResponseData(`${e.toString()}`);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ return (
+
+
+
+ Request
+
+
+
+ {new Array(enteredRows).fill(0).map((_, index) => (
+ {index + 1}
+ ))}
+
+
{
+ setVal(e.target.value);
+ }}
+ style={{ resize: 'none' }}
+ placeholder="JSON RPC playground is a simple tool to help you test queries, click to enter you requests."
+ >
+
+
+
+ {
+ fetchRpc();
+ }}
+ >
+ Send Request
+
+
+
+
+
+
+ Response
+
+
+ {responseData}
+
+
+
+ );
+};
+export default RpcPlayground;
diff --git a/src/components/RpcPlayground/index.module.less b/src/components/RpcPlayground/index.module.less
new file mode 100644
index 000000000..9864645b0
--- /dev/null
+++ b/src/components/RpcPlayground/index.module.less
@@ -0,0 +1,46 @@
+.rpcPlayground {
+ display: flex;
+ padding: 16px;
+ border-radius: 0px 0px 16px 16px;
+ background: #2A3546;
+
+ &Editor {
+ flex: 1;
+ padding: 16px;
+ background: #1F2A3B;
+ border-radius: 10px;
+ position: relative;
+
+ .rows {
+ display: flex;
+ flex-direction: column;
+ color: var(--sq-gray600);
+ font-size: 14px;
+ line-height: 1.5714285714285714;
+ padding-top: 2px;
+ }
+
+ :global {
+ .ant-input {
+ background: #1F2A3B;
+ border: 1px solid #1F2A3B;
+ color: var(--sq-gray500);
+ padding: 0;
+ font-family: var(--sq-font-family);
+ &:focus {
+ box-shadow: none;
+ }
+
+ &::placeholder {
+ color: var(--sq-gary500);
+ }
+ }
+ }
+ }
+
+ &Response {
+ flex: 1;
+ padding: 16px;
+
+ }
+}
\ No newline at end of file
diff --git a/src/components/Spinner/Spinner.tsx b/src/components/Spinner/Spinner.tsx
index 5822335d0..466f3427e 100644
--- a/src/components/Spinner/Spinner.tsx
+++ b/src/components/Spinner/Spinner.tsx
@@ -2,8 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
import * as React from 'react';
-import LoadingOutlined from '@ant-design/icons/LoadingOutlined';
-import { Spin } from 'antd';
+import { Spinner as SubqlSpinner } from '@subql/components';
import styles from './Spinner.module.css';
@@ -12,11 +11,9 @@ type Props = {
};
const Spinner: React.FC = ({ size }) => {
- const antIcon = ;
-
return (
-
+
);
};
diff --git a/src/hooks/useProjectList.module.less b/src/hooks/useProjectList.module.less
index 4c8539db9..0e4b7c119 100644
--- a/src/hooks/useProjectList.module.less
+++ b/src/hooks/useProjectList.module.less
@@ -8,7 +8,7 @@
.typeFilter {
display: flex;
- justify-content: center;
+ // justify-content: center;
margin-bottom: 40px;
:global {
diff --git a/src/hooks/useProjectList.tsx b/src/hooks/useProjectList.tsx
index 4accda27b..c1e38b08d 100644
--- a/src/hooks/useProjectList.tsx
+++ b/src/hooks/useProjectList.tsx
@@ -5,12 +5,13 @@ import React, { useMemo, useState } from 'react';
import SearchOutlined from '@ant-design/icons/SearchOutlined';
import { ProjectCard } from '@components';
import { useProjectMetadata } from '@containers';
+import { PublishNewProjectModal } from '@pages/studio/Home/Home';
import { SubqlCheckbox } from '@subql/components';
import { ProjectFieldsFragment, ProjectsOrderBy, ProjectType } from '@subql/network-query';
import { useAsyncMemo, useGetProjectLazyQuery, useGetProjectsLazyQuery } from '@subql/react-hooks';
import { categoriesOptions, notEmpty, rpcCategoriesOptions } from '@utils';
import { useInfiniteScroll, useMount } from 'ahooks';
-import { Input, Radio, Skeleton, Typography } from 'antd';
+import { Button, Input, Radio, Skeleton, Typography } from 'antd';
import { useGetDeploymentManifest } from './useGetDeploymentManifest';
import { useLocalProjects } from './useLocalProjects';
@@ -63,6 +64,7 @@ export const useProjectList = (props: UseProjectListProps = {}) => {
// assum there at lease have 11 projects
const [total, setTotal] = React.useState(10);
const [inSearchMode, setInSearchMode] = React.useState(false);
+ const [showPublishModal, setShowPublishModal] = React.useState(false);
const { getProjectBySearch } = useLocalProjects();
@@ -236,6 +238,23 @@ export const useProjectList = (props: UseProjectListProps = {}) => {
buttonStyle="solid"
size="large"
/>
+
+ {
+ setShowPublishModal(true);
+ }}
+ >
+ Publish New Project
+
+ {
+ setShowPublishModal(val);
+ }}
+ >
diff --git a/src/i18n/en/explorer.ts b/src/i18n/en/explorer.ts
index c8110ca03..da83cb1ba 100644
--- a/src/i18n/en/explorer.ts
+++ b/src/i18n/en/explorer.ts
@@ -105,7 +105,7 @@ const translation = {
indexer: 'indexer',
validityPeriod: 'Validity Period',
non: 'There are no flex plans for this project yet.',
- requestToken: 'To start testing your queries in the GraphQL playground, simply request a trial token.',
+ requestToken: 'To start testing your queries in the {{type}} playground, simply request a trial token.',
remainLimit: 'Remain requests limit: {{limit}}',
expireTime: 'Token expires in {{time}}',
},
diff --git a/src/images/rpcPlayground.tsx b/src/images/rpcPlayground.tsx
new file mode 100644
index 000000000..934c63f29
--- /dev/null
+++ b/src/images/rpcPlayground.tsx
@@ -0,0 +1,60 @@
+// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
+// SPDX-License-Identifier: Apache-2.0
+
+import { FC } from 'react';
+
+export type Icon = {
+ color?: string;
+ width?: number;
+ height?: number;
+ style?: React.CSSProperties;
+};
+
+const RpcPlaygroundIcon: FC
= ({ color = '#fff', width = 18, height = 18, style }) => {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+export default RpcPlaygroundIcon;
diff --git a/src/pages/consumer/Playground/AuthPlayground.tsx b/src/pages/consumer/Playground/AuthPlayground.tsx
index 285d8deb7..e80a78a8a 100644
--- a/src/pages/consumer/Playground/AuthPlayground.tsx
+++ b/src/pages/consumer/Playground/AuthPlayground.tsx
@@ -4,7 +4,9 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { BreadcrumbNav } from '@components';
+import RpcPlayground from '@components/RpcPlayground/RpcPlayground';
import { Spinner } from '@subql/components';
+import { ProjectType } from '@subql/network-query';
import { Table } from 'antd';
import { ColumnsType } from 'antd/lib/table';
@@ -33,6 +35,7 @@ interface AuthPlaygroundProps {
columns?: ColumnsType;
dataSource?: any[];
rowKey?: string;
+ type: ProjectType;
loading?: boolean;
requireAuth: boolean;
@@ -53,6 +56,7 @@ export const AuthPlayground: React.FC = ({
columns,
dataSource,
rowKey,
+ type,
loading,
requireAuth,
@@ -82,7 +86,13 @@ export const AuthPlayground: React.FC = ({
{loading && }
{requireAuth && }
- {playgroundVisible && }
+ {type === ProjectType.SUBQUERY && playgroundVisible && }
+ {type === ProjectType.RPC && playgroundVisible && (
+
+ )}
);
diff --git a/src/pages/consumer/Playground/FlexPlayground.tsx b/src/pages/consumer/Playground/FlexPlayground.tsx
index 5290885a6..c86ddf815 100644
--- a/src/pages/consumer/Playground/FlexPlayground.tsx
+++ b/src/pages/consumer/Playground/FlexPlayground.tsx
@@ -7,7 +7,7 @@ import { useNavigate, useParams } from 'react-router';
import { NotificationType, openNotification } from '@components/Notification';
import { FetcherParams } from '@graphiql/toolkit';
import { Spinner, TableTitle } from '@subql/components';
-import { StateChannelFieldsFragment as ConsumerFlexPlan } from '@subql/network-query';
+import { ProjectType, StateChannelFieldsFragment as ConsumerFlexPlan } from '@subql/network-query';
import { renderAsync, useGetConsumerFlexPlanQuery } from '@subql/react-hooks';
import { TableProps } from 'antd';
import { BigNumber } from 'ethers';
@@ -202,6 +202,7 @@ export const FlexPlayground: React.FC = () => {
headerText={t('plans.category.myFlexPlans')}
deploymentId={flexPlan?.deployment?.id ?? ''}
projectMetadata={flexPlan?.deployment?.project?.metadata}
+ type={flexPlan.deployment?.project?.type || ProjectType.SUBQUERY}
columns={columns}
dataSource={[flexPlan]}
rowKey={'id'}
diff --git a/src/pages/consumer/Playground/SAPlayground.tsx b/src/pages/consumer/Playground/SAPlayground.tsx
index 1949741cb..16d219c00 100644
--- a/src/pages/consumer/Playground/SAPlayground.tsx
+++ b/src/pages/consumer/Playground/SAPlayground.tsx
@@ -7,7 +7,7 @@ import { useLocation, useNavigate } from 'react-router';
import { NotificationType, openNotification } from '@components/Notification';
import { FetcherParams } from '@graphiql/toolkit';
import { useIndexerMetadata } from '@hooks';
-import { ServiceAgreementFieldsFragment as ServiceAgreement } from '@subql/network-query';
+import { ProjectType, ServiceAgreementFieldsFragment as ServiceAgreement } from '@subql/network-query';
import { TableProps } from 'antd';
import i18next from 'i18next';
import moment from 'moment';
@@ -166,12 +166,18 @@ export const SAPlayground: React.FC = () => {
const requireAuth = queryable === false && !isCheckingAuth;
const showPlayground = !!(queryable && queryUrl && !isCheckingAuth);
+ if (!serviceAgreement) {
+ navigate('/consumer/service-agreements');
+ return
;
+ }
+ console.warn(serviceAgreement);
return (
= ({
{t('serviceAgreements.playground.comingSoon')}
);
+
return (
{
@@ -35,7 +36,13 @@ export const AllIndexers: React.FC = () => {
),
{
loading: () => ,
- error: (error) => {`Error: Failed to get Indexers: ${error.message}`} ,
+ error: (error) => {
+ if (isRPCError(error)) {
+ return ;
+ }
+
+ return {`Error: Failed to get Indexers: ${error.message}`} ;
+ },
data: (data) => {
if (!data || data?.totalCount === 0) {
;
diff --git a/src/pages/explorer/Home/Home.module.css b/src/pages/explorer/Home/Home.module.css
index bf9b29275..18448c381 100644
--- a/src/pages/explorer/Home/Home.module.css
+++ b/src/pages/explorer/Home/Home.module.css
@@ -7,7 +7,7 @@
.header {
display: flex;
flex-direction: column;
- margin-bottom: 72px;
+ margin-bottom: 18px;
}
.headerTitle {
diff --git a/src/pages/explorer/Home/Home.tsx b/src/pages/explorer/Home/Home.tsx
index 0325152bb..b1a6b700c 100644
--- a/src/pages/explorer/Home/Home.tsx
+++ b/src/pages/explorer/Home/Home.tsx
@@ -5,9 +5,7 @@ import * as React from 'react';
import { useTranslation } from 'react-i18next';
import { useNavigate } from 'react-router';
import { useProjectList } from '@hooks/useProjectList';
-import { PublishNewProjectModal } from '@pages/studio/Home/Home';
import { Typography } from '@subql/components';
-import { Button } from 'antd';
import { ROUTES } from '../../../utils';
import styles from './Home.module.css';
@@ -17,7 +15,6 @@ const { PROJECT_NAV } = ROUTES;
// TODO move to components
export const Header: React.FC = () => {
const { t } = useTranslation();
- const [showPublishModal, setShowPublishModal] = React.useState(false);
return (
@@ -26,23 +23,7 @@ export const Header: React.FC = () => {
{t('explorer.home.headerDesc')}
- {
- setShowPublishModal(true);
- }}
- >
- Publish New Project
-
- {
- setShowPublishModal(val);
- }}
- >
);
};
diff --git a/src/pages/explorer/Project/Project.tsx b/src/pages/explorer/Project/Project.tsx
index 56d96d521..bcc507515 100644
--- a/src/pages/explorer/Project/Project.tsx
+++ b/src/pages/explorer/Project/Project.tsx
@@ -45,7 +45,7 @@ const ProjectInner: React.FC = () => {
{ link: `${OVERVIEW}${location.search}`, label: t('explorer.project.tab1') },
{
link: `${INDEXERS}${location.search}`,
- label: asyncProject.data?.type === ProjectType.RPC ? 'RPC Endpoints' : t('explorer.project.tab2'),
+ label: asyncProject.data?.type === ProjectType.RPC ? 'RPC Providers' : t('explorer.project.tab2'),
},
{ link: `${SERVICE_AGREEMENTS}${location.search}`, label: t('explorer.project.tab3') },
];
@@ -158,7 +158,10 @@ const ProjectInner: React.FC = () => {
/>
}
/>
- } />
+ }
+ />
{
},
});
- const [showCreateModal, setShowCreateModal] = React.useState(false);
- const enableCreateModal = () => setShowCreateModal(true);
-
return (
My Projects
-
- Publish New Project
-
-
{
- setShowCreateModal(val);
- }}
- />
-
{listsWithSearch}
);