20 | {t('indexer.indexers')}
21 |
22 | Which operator should I delegate to?
23 |
24 |
25 | }
26 | desc={t('allIndexers.desc')}
27 | />
28 |
29 | >
30 | );
31 | };
32 |
33 | export default Indexers;
34 |
--------------------------------------------------------------------------------
/src/pages/delegator/MyDelegation.module.css:
--------------------------------------------------------------------------------
1 | .delegatingCard {
2 | margin: 1rem 0;
3 | width: 20vw;
4 | }
5 |
6 | .doDelegate {
7 | margin: 1rem 0;
8 | }
9 |
10 | .rewardsLineChart {
11 | width: 100%;
12 | }
13 |
14 | .delegationInfo {
15 | margin: 24px 0px;
16 | }
17 |
18 | .newCard {
19 | width: auto;
20 | margin-right: 24px;
21 | min-width: 364px;
22 | height: 340px;
23 | }
24 |
25 | @media (max-width: 768px) {
26 | .rewardsLineChart {
27 | width: 100%;
28 | margin-top: 16px;
29 | }
30 |
31 | .delegationInfo {
32 | margin: 24px 0px;
33 | flex-wrap: wrap;
34 | }
35 |
36 | .newCard {
37 | width: 100% !important;
38 | min-width: 364px;
39 | height: 340px;
40 | margin-right: 0;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/pages/delegator/TopIndexers/TopIndexers.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import * as React from 'react';
5 | import { useTranslation } from 'react-i18next';
6 | import { AppPageHeader } from '@components/AppPageHeader';
7 | import { TOP_100_INDEXERS } from '@containers';
8 | import { Spinner } from '@subql/components';
9 | import { useGetTopIndexersQuery } from '@subql/react-hooks';
10 | import { Typography } from 'antd';
11 |
12 | import { renderAsync } from '../../../utils';
13 | import { TopIndexerList } from './TopIndexersList';
14 |
15 | export const TopIndexers: React.FC = () => {
16 | const { t } = useTranslation();
17 | const topIndexers = useGetTopIndexersQuery({
18 | context: { clientName: TOP_100_INDEXERS },
19 | });
20 |
21 | return (
22 |
23 |
24 | {renderAsync(topIndexers, {
25 | loading: () =>
,
26 | error: (error) => (
27 | <>
28 |
Error: {' '}
29 |
{`Failed to get top Indexers: ${error.message}`}
30 | >
31 | ),
32 | data: (data) => {
33 | const topIndexers = data?.indexerPrograms;
34 |
35 | if (!topIndexers) {
36 | return
{t('topIndexers.nonData')};
37 | }
38 | return
;
39 | },
40 | })}
41 |
42 | );
43 | };
44 |
45 | export default TopIndexers;
46 |
--------------------------------------------------------------------------------
/src/pages/delegator/TopIndexers/TopIndexersList.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | background: white;
3 | padding: 1rem;
4 | overflow: auto;
5 | }
6 |
7 | .indexerListHeader {
8 | margin: 1rem 0 2rem 0;
9 | display: flex;
10 | justify-content: flex-end;
11 | }
12 |
13 | .indexerSearch {
14 | width: 360px;
15 | }
16 |
--------------------------------------------------------------------------------
/src/pages/delegator/index.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import * as React from 'react';
5 | import { Outlet } from 'react-router-dom';
6 | import { AppSidebar } from '@components/AppSidebar';
7 | import { DelegatorSidebar } from '@utils/links';
8 |
9 | const Delegator: React.FC = () => {
10 | return (
11 |
12 |
13 |
14 | );
15 | };
16 |
17 | export default Delegator;
18 |
--------------------------------------------------------------------------------
/src/pages/explorer/Explorer.module.css:
--------------------------------------------------------------------------------
1 | .account {
2 | display: flex;
3 | flex-direction: column;
4 | width: 100%;
5 | }
6 |
7 | .page {
8 | position: relative;
9 | height: 100%;
10 | }
11 |
--------------------------------------------------------------------------------
/src/pages/explorer/FlexPlans/CreateHostingPlan/index.module.less:
--------------------------------------------------------------------------------
1 | .billBalance {
2 | margin: 1rem 0;
3 | }
4 |
5 | .billingCard {
6 | border-radius: 8px;
7 | border: 1px solid var(--sq-gray200);
8 | width: 100%;
9 | padding: 16px 24px;
10 | margin-bottom: 24px;
11 | }
12 |
13 | .billingButton {
14 | background: var(--sq-blue600);
15 | border-color: var(--sq-blue600);
16 | }
17 |
18 | .createFlexPlanModal {
19 | :global {
20 | .ant-form-item {
21 | margin-bottom: 0;
22 | }
23 |
24 | .ant-form-item-required.ant-form-item-required.ant-form-item-required.ant-form-item-required {
25 | &::before {
26 | display: none;
27 | }
28 | }
29 |
30 | .ant-input-number-group-wrapper {
31 | width: 100%;
32 |
33 | .ant-input-number {
34 | border-right: none;
35 | }
36 | .ant-input-number-group-addon {
37 | background: none;
38 | color: var(--sq-gray500);
39 | }
40 |
41 | &:hover {
42 | .ant-input-number-group-addon {
43 | border-color: #4096ff;
44 | }
45 | }
46 |
47 | .ant-input-number-focused ~ .ant-input-number-group-addon {
48 | border-color: #4096ff;
49 | }
50 |
51 | .ant-input-number-status-error ~ .ant-input-number-group-addon {
52 | border-color: #ff4d4f;
53 | }
54 | }
55 |
56 | .ant-input-number-handler-wrap {
57 | display: none;
58 | }
59 |
60 | .ant-input-number {
61 | width: 100%;
62 | padding: 12px;
63 | font-size: 16px;
64 | .ant-input-number-input {
65 | height: 24px;
66 | padding: 0;
67 | }
68 | }
69 | }
70 | }
--------------------------------------------------------------------------------
/src/pages/explorer/FlexPlans/FlexPlans.module.less:
--------------------------------------------------------------------------------
1 | .starContainer {
2 | width: 1.5rem;
3 | }
4 |
5 | .star {
6 | color: var(--yellow700);
7 | width: 1.2rem;
8 | height: 1.2rem;
9 | }
10 |
--------------------------------------------------------------------------------
/src/pages/explorer/FlexPlans/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export * from './FlexPlans';
5 |
--------------------------------------------------------------------------------
/src/pages/explorer/Home/Home.module.css:
--------------------------------------------------------------------------------
1 | .explorer {
2 | padding: 72px 80px;
3 | display: flex;
4 | flex-direction: column;
5 | }
6 |
7 | .header {
8 | display: flex;
9 | flex-direction: column;
10 | margin-bottom: 18px;
11 | align-items: center;
12 | }
13 |
14 | .headerTitle {
15 | font-weight: 500;
16 | font-size: 32px;
17 | line-height: 38px;
18 | }
19 |
20 | .line {
21 | background: var(--sq-gradient);
22 | margin-top: 24px;
23 | width: 48px;
24 | height: 10px;
25 | }
26 |
27 | .typographySecondary {
28 | width: 565px;
29 | margin-top: 16px;
30 | }
31 |
32 | @media (max-width: 768px) {
33 | .typographySecondary {
34 | width: auto;
35 | margin-top: 16px;
36 | }
37 |
38 | .explorer {
39 | padding: 30px;
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/pages/explorer/Home/Home.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import * as React from 'react';
5 | import { useTranslation } from 'react-i18next';
6 | import { useRouteQuery } from '@hooks';
7 | import { useProjectList } from '@hooks/useProjectList';
8 | import { Typography } from '@subql/components';
9 | import { ProjectType } from '@subql/network-query';
10 |
11 | import styles from './Home.module.css';
12 |
13 | // TODO move to components
14 | export const Header: React.FC = () => {
15 | const { t } = useTranslation();
16 |
17 | return (
18 |
19 |
20 | {t('explorer.home.header')}
21 |
22 |
23 |
24 | {t('explorer.home.headerDesc')}
25 |
26 |
27 |
28 | );
29 | };
30 |
31 | const Home: React.FC = () => {
32 | const query = useRouteQuery();
33 |
34 | const { listsWithSearch } = useProjectList({
35 | showTopProject: false,
36 | defaultFilterProjectType: query.get('category') === 'rpc' ? ProjectType.RPC : ProjectType.SUBQUERY,
37 | });
38 |
39 | return (
40 |
41 |
42 |
43 | {listsWithSearch}
44 |
45 |
46 | );
47 | };
48 |
49 | export default Home;
50 |
--------------------------------------------------------------------------------
/src/pages/explorer/Project/Project.module.less:
--------------------------------------------------------------------------------
1 | .container {
2 | width: 100%;
3 | min-height: 85%;
4 | }
5 |
6 | .progress {
7 | margin: 40px 0;
8 | }
9 |
10 | .upper {
11 | padding: 24px 78px;
12 | }
13 |
14 | .projectHeader {
15 | margin: 24px 0;
16 | }
17 |
18 | .contentOverview{
19 | padding: 0px 78px 24px;
20 | }
21 |
22 | @media (max-width: 768px) {
23 | .container {
24 | display: flex;
25 | flex-direction: column;
26 | }
27 | .upper {
28 | padding: 24px 25px;
29 | }
30 | .contentOverview{
31 | padding: 0px 24px 24px;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/pages/explorer/Project/type.ts:
--------------------------------------------------------------------------------
1 | export enum ProjectActionArgv {
2 | BOOST = 'boost',
3 | CREATE_PLAN = 'createPlan',
4 | }
5 |
--------------------------------------------------------------------------------
/src/pages/explorer/index.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import * as React from 'react';
5 | import { Outlet } from 'react-router';
6 | import { Footer } from '@subql/components';
7 |
8 | import styles from './Explorer.module.css';
9 |
10 | const Explorer: React.FC = () => {
11 | return (
12 |
18 | );
19 | };
20 |
21 | export default Explorer;
22 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyDelegators/MyDelegators.module.css:
--------------------------------------------------------------------------------
1 | .content {
2 | background: white;
3 | padding: 2rem;
4 | overflow: auto;
5 | min-height: 80%;
6 | }
7 |
8 | .offers {
9 | margin: 1rem 0;
10 | }
11 |
12 | .noDelegatorsContainer {
13 | margin: 10vh auto;
14 | width: 30vw;
15 | display: flex;
16 | flex-direction: column;
17 | text-align: center;
18 | }
19 |
20 | .description {
21 | margin-top: 3vh;
22 | }
23 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyDelegators/OwnDelegator.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | margin: 1rem 0;
3 | }
4 |
5 | .text {
6 | color: var(--gray500);
7 | }
8 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/Create/Create.module.less:
--------------------------------------------------------------------------------
1 | .btns {
2 | margin-top: 2rem;
3 | }
4 |
5 | .btn {
6 | margin: 0 1rem;
7 | }
8 |
9 | .select {
10 | margin: 1rem 0;
11 | }
12 |
13 | .inputTitle {
14 | margin: 6px 0;
15 | color: var(--gray700);
16 | }
17 |
18 | .projectName {
19 | color: var(--gray700);
20 | padding-right: 5px;
21 | }
22 |
23 | .projectDeploymentId {
24 | font-size: 12px;
25 | color: var(--gray500);
26 | }
27 |
28 | .deploymentOption {
29 | padding-top: 0.5rem;
30 | }
31 |
32 | .marginSpace {
33 | margin: 1rem 0;
34 | }
35 |
36 | .templateList {
37 | height: 350px;
38 | overflow: auto;
39 | }
40 |
41 | .project {
42 | display: flex;
43 | flex-direction: column;
44 | }
45 |
46 | .usdcAlert {
47 | padding: 9px 16px;
48 | border-radius: 8px;
49 | border: 1px solid rgba(58, 160, 255, 0.5);
50 | background: rgba(58, 160, 255, 0.08);
51 | align-items: flex-start;
52 |
53 | :global {
54 | .ant-alert-icon.ant-alert-icon {
55 | color: var(--sq-info);
56 | margin-top: 4px;
57 | }
58 | }
59 | }
60 |
61 | .planSelector:global(.ant-select-single.ant-select-lg) {
62 | height: 60px;
63 | }
64 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/Create/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export * from './Create';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/Default/Default.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import * as React from 'react';
5 | import { useTranslation } from 'react-i18next';
6 | import { EmptyList } from '@components/EmptyList';
7 | import { useWeb3 } from '@containers';
8 | import { Spinner, Typography } from '@subql/components';
9 | import { useGetPlansQuery } from '@subql/react-hooks';
10 | import { mapAsync, notEmpty, renderAsyncArray } from '@utils';
11 |
12 | import List from '../List';
13 |
14 | export const Default: React.FC = () => {
15 | const { account } = useWeb3();
16 | const { t } = useTranslation();
17 | const plans = useGetPlansQuery({ variables: { address: account ?? '' }, pollInterval: 10000 });
18 |
19 | return (
20 |
21 | {renderAsyncArray(
22 | mapAsync((d) => d.plans?.nodes.filter(notEmpty), plans),
23 | {
24 | loading: () => ,
25 | error: (e) => {`Error loading plans: ${e}`},
26 | empty: () => (
27 |
32 | ),
33 | data: (data) => (
34 | parseInt(a.id || '0x00', 16) - parseInt(b.id || '0x00', 16))}
36 | onRefresh={() => plans.refetch()}
37 | title={t('plans.default.title')}
38 | />
39 | ),
40 | },
41 | )}
42 |
43 | );
44 | };
45 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/Default/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export * from './Default';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/List/List.module.less:
--------------------------------------------------------------------------------
1 | .btns {
2 | display: flex;
3 | justify-content: flex-end;
4 | margin-top: 2rem;
5 | }
6 |
7 | .btn {
8 | margin: 0 1rem;
9 | }
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/List/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export { default } from './List';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/Plans.module.css:
--------------------------------------------------------------------------------
1 | .tabs {
2 | margin-top: 2vh;
3 | display: flex;
4 | justify-content: space-between;
5 | align-items: center;
6 | }
7 |
8 | .create {
9 | height: 40px;
10 | flex-shrink: 0;
11 | }
12 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/Specific/Specific.module.css:
--------------------------------------------------------------------------------
1 | .plans {
2 | margin: 16px 0;
3 | }
4 |
5 | .plan {
6 | border: 1px solid var(--gray300);
7 | border-radius: 6px;
8 | padding: 16px;
9 | margin-bottom: 26px;
10 | }
11 |
12 | .header {
13 | margin-bottom: 16px;
14 | }
15 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyPlans/Specific/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export { default } from './Specific';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyProjects/AutoReduceOverAllocation/index.module.less:
--------------------------------------------------------------------------------
1 | .autoReduceAllocation {
2 | flex-direction: column;
3 | gap: 4px;
4 | padding: 9px 16px;
5 | margin-bottom: 24px;
6 |
7 | &.enabled {
8 | border-radius: 8px;
9 | border: 1px solid rgba(58, 160, 255, 0.50);
10 | background: rgba(58, 160, 255, 0.08);
11 | }
12 |
13 | &.disabled {
14 | border-radius: 8px;
15 | border: 1px solid rgba(241, 88, 91, 0.50);
16 | background: rgba(241, 88, 91, 0.08);
17 | }
18 | }
--------------------------------------------------------------------------------
/src/pages/indexer/MyProjects/MyProjects.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | height: 100%;
3 | }
4 |
5 | .content {
6 | background: white;
7 | padding: 2rem;
8 | overflow: auto;
9 | min-height: 80%;
10 | }
11 |
12 | .offers {
13 | margin: 1rem 0;
14 | }
15 |
16 | .noOffersContainer {
17 | margin: 15vh auto;
18 | width: 35vw;
19 | display: flex;
20 | flex-direction: column;
21 | text-align: center;
22 | }
23 |
24 | .description {
25 | margin-top: 3vh;
26 | }
27 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyProjects/OwnDeployments/OwnDeployments.module.css:
--------------------------------------------------------------------------------
1 | .container {
2 | margin: 1rem 0;
3 | }
4 |
5 | .desc {
6 | margin: 1rem 0 1rem -8px;
7 | }
8 |
9 | .progress {
10 | width: 100%;
11 | }
12 |
13 | .info {
14 | display: flex;
15 | gap: 24px;
16 | }
17 |
18 | .totalStake {
19 | box-shadow: none;
20 | margin-bottom: 24px;
21 | flex: 1 1 0%;
22 | }
23 |
24 | .stakeInfo {
25 | display: flex;
26 | gap: 12px;
27 | flex-direction: column;
28 | }
29 |
30 | @media (max-width: 768px) {
31 | .info {
32 | display: flex;
33 | gap: 1px;
34 | flex-wrap: wrap;
35 | width: 100%;
36 | flex-direction: column;
37 | }
38 |
39 | .totalStake {
40 | width: 100%;
41 | box-shadow: none;
42 | margin-bottom: 24px;
43 | flex: 1 1 0%;
44 | }
45 |
46 | .stakeInfo {
47 | display: flex;
48 | gap: 1px;
49 | flex-wrap: wrap;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyProjects/OwnDeployments/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export * from './OwnDeployments';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyStaking/DoStake/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export { DoStake } from './DoStake';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyStaking/Indexing/Indexing.module.css:
--------------------------------------------------------------------------------
1 | .nextItem {
2 | display: flex;
3 | }
4 |
5 | .nextIcon {
6 | height: 100%;
7 | margin-right: 6px;
8 | color: var(--gray500);
9 | }
10 |
11 | .btns {
12 | display: flex;
13 | margin: 1rem 0;
14 | }
15 |
16 | .textGroup {
17 | margin: 0.25rem 0;
18 | display: flex;
19 | flex-direction: column;
20 | }
21 |
22 | .grayText {
23 | color: var(--gray500) !important;
24 | }
25 |
26 | .learnMoreContainer {
27 | display: flex;
28 | }
29 |
30 | .learnMoreText {
31 | margin-right: 0.5rem;
32 | }
33 |
34 | .learnMoreBtn {
35 | font-size: 14px;
36 | line-height: 22px;
37 | }
38 |
39 | .notIndexerContainer {
40 | width: 100%;
41 | height: 70%;
42 | display: flex;
43 | justify-content: center;
44 | align-items: center;
45 | }
46 |
47 | .notIndexer {
48 | width: 45%;
49 | display: flex;
50 | flex-direction: column;
51 | justify-content: center;
52 | row-gap: 1.25rem;
53 | }
54 |
55 | .doStakeContainer {
56 | display: flex;
57 | justify-content: center;
58 | margin: 1rem 0;
59 | }
60 |
61 | .doStake {
62 | width: 55%;
63 | text-align: center;
64 | display: flex;
65 | flex-direction: column;
66 | }
67 |
68 | .doStakeTitle {
69 | font-weight: 500;
70 | font-size: 24px;
71 | line-height: 36px;
72 | }
73 |
74 | .doStakeText {
75 | font-size: 16px;
76 | line-height: 24px;
77 | }
78 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyStaking/Indexing/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export * from './Indexing';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyStaking/MyStaking.module.css:
--------------------------------------------------------------------------------
1 | .grayText {
2 | color: var(--gray500);
3 | }
4 |
5 | .container {
6 | display: flex;
7 | background-color: var(--sq-gray200);
8 | width: 100%;
9 | min-height: 100%;
10 | }
11 |
12 | .sidebar {
13 | width: 25%;
14 | }
15 |
16 | .content {
17 | width: 100%;
18 | padding: 1rem 2rem;
19 | overflow: auto;
20 | }
21 |
22 | .profile {
23 | width: 100%;
24 | height: 100%;
25 | display: flex;
26 | flex-direction: column;
27 | padding: 1rem 0;
28 | }
29 |
30 | .stakingHeader {
31 | margin: 1.25rem 0;
32 |
33 | display: flex;
34 | justify-content: space-between;
35 | align-items: flex-end;
36 | }
37 |
38 | .stakingActions {
39 | display: flex;
40 | }
41 |
42 | .stakingAmount {
43 | width: 280px;
44 | }
45 |
46 | .tabList {
47 | display: flex;
48 | margin-top: 2rem;
49 | text-align: center;
50 | }
51 |
52 | .line {
53 | background: var(--sq-gradient);
54 | height: 2px;
55 | }
56 |
--------------------------------------------------------------------------------
/src/pages/indexer/MyStaking/SetCommissionRate/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export * from './SetCommissionRate';
5 |
--------------------------------------------------------------------------------
/src/pages/indexer/index.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import * as React from 'react';
5 | import { Outlet } from 'react-router';
6 | import { AppSidebar } from '@components/AppSidebar';
7 | import { IndexerSidebar } from '@utils/links';
8 |
9 | const Indexer: React.FC = () => {
10 | return (
11 |
12 |
13 |
14 | );
15 | };
16 |
17 | export default Indexer;
18 |
--------------------------------------------------------------------------------
/src/pages/projects/Create/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export { default } from './Create';
5 |
--------------------------------------------------------------------------------
/src/pages/projects/Home/Home.module.less:
--------------------------------------------------------------------------------
1 | .typeCard {
2 | transition: all 0.3s;
3 | cursor: pointer;
4 | &:hover {
5 | border-color: var(--sq-blue600);
6 | }
7 | }
8 | .active {
9 | border-color: var(--sq-blue600);
10 | }
11 |
--------------------------------------------------------------------------------
/src/pages/projects/Home/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export { default } from './Home';
5 |
--------------------------------------------------------------------------------
/src/pages/projects/Project/Project.module.less:
--------------------------------------------------------------------------------
1 | .deployments {
2 | padding-top: 32px;
3 | display: flex;
4 | align-items: flex-start;
5 | flex-direction: column;
6 | }
7 |
8 | .deployButton {
9 | margin-top: 32px;
10 | }
11 |
12 | .content {
13 | padding: 0 80px 80px 80px;
14 | display: flex;
15 | flex-direction: column;
16 | gap: 24px;
17 | }
18 |
19 | .tabContainer {
20 | display: flex;
21 | column-gap: 1rem;
22 | margin: 1rem 0;
23 | }
24 |
25 | .tab {
26 | font-size: 18px;
27 | font-weight: 500;
28 | cursor: pointer;
29 | }
30 |
31 |
32 | .markdownWrapper {
33 | :global {
34 | .subql-markdown-preview {
35 | height: 440px;
36 | overflow: auto;
37 | }
38 | }
39 | }
--------------------------------------------------------------------------------
/src/pages/projects/Project/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export { default } from './Project';
5 |
--------------------------------------------------------------------------------
/src/pages/projects/index.module.css:
--------------------------------------------------------------------------------
1 | .networkContainer {
2 | display: flex;
3 | flex-direction: column;
4 | justify-content: center;
5 | align-items: center;
6 | padding: 50px 0;
7 | }
8 |
9 | .networkTitle {
10 | font-family: Futura;
11 | font-weight: 500;
12 | font-size: 24px;
13 | line-height: 36px;
14 | color: var(--gray900);
15 | padding-bottom: 8px;
16 | }
17 |
18 | .networkSubtitle {
19 | font-size: 16px;
20 | line-height: 24px;
21 |
22 | /* identical to box height, or 150% */
23 | letter-spacing: 0.3px;
24 | padding-bottom: 8px;
25 | }
26 |
--------------------------------------------------------------------------------
/src/pages/projects/index.tsx:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import * as React from 'react';
5 | import { Route, Routes } from 'react-router';
6 | import { WalletRoute } from '@components/WalletRoute';
7 | import { Footer } from '@subql/components';
8 |
9 | import Create from './Create';
10 | import Home from './Home';
11 | import Project from './Project';
12 |
13 | const Studio: React.FC = () => {
14 | return (
15 |
18 |
19 | } />
20 | } />
21 | } />
22 |
23 |
24 |
25 |
26 | }
27 | >
28 | );
29 | };
30 |
31 | export default Studio;
32 |
--------------------------------------------------------------------------------
/src/react-i18next.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { resources } from './i18n';
5 |
6 | declare module 'react-i18next' {
7 | interface CustomTypeOptions {
8 | resources: (typeof resources)['en'];
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/stores/chatbox.ts:
--------------------------------------------------------------------------------
1 | import { ChatBoxRef } from '@subql/components';
2 | import { create } from 'zustand';
3 |
4 | export type chatBoxStore = {
5 | chatBoxRef?: ChatBoxRef;
6 | setChatBoxRef: (ref: ChatBoxRef) => void;
7 | };
8 |
9 | export const useChatBoxStore = create((set) => ({
10 | chatBoxRef: undefined,
11 | setChatBoxRef(ref) {
12 | this.chatBoxRef = ref;
13 | },
14 | }));
15 |
--------------------------------------------------------------------------------
/src/stores/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export * from './web3Account';
5 |
--------------------------------------------------------------------------------
/src/stores/web3Account.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { RootContractSDK } from '@subql/contract-sdk/rootSdk';
5 | import { ContractSDK } from '@subql/contract-sdk/sdk';
6 | import { ContractClient } from '@subql/network-clients';
7 | import { ethers } from 'ethers';
8 | import { create } from 'zustand';
9 |
10 | /**
11 | *
12 | * Web3Account
13 | *
14 | */
15 |
16 | interface Web3Store {
17 | error?: any;
18 | setError: (error: any) => void;
19 |
20 | isInitialAccount?: boolean;
21 | setIsInitialAccount: (isInitialAccount: boolean) => void;
22 |
23 | contracts?: ContractSDK;
24 | setContracts: (contracts: ContractSDK) => void;
25 |
26 | rootContracts?: RootContractSDK;
27 | setRootContracts: (rootContracts: RootContractSDK) => void;
28 |
29 | contractClient?: ContractClient;
30 | setContractClient: (contracts: ContractClient) => void;
31 | }
32 |
33 | export const useWeb3Store = create()((set) => ({
34 | contracts: undefined,
35 | isInitialAccount: false,
36 | rootContracts: undefined,
37 | setRootContracts: (rootContracts: RootContractSDK | undefined) => set((state) => ({ ...state, rootContracts })),
38 |
39 | setIsInitialAccount: (isInitialAccount: boolean) => set((state) => ({ ...state, isInitialAccount })),
40 |
41 | setError: (error: Error) => set((state) => ({ ...state, error })),
42 |
43 | setContracts: (contracts: ContractSDK | undefined) => set((state) => ({ ...state, contracts })),
44 |
45 | setContractClient: (contractClient: ContractClient | undefined) => set((state) => ({ ...state, contractClient })),
46 | }));
47 |
--------------------------------------------------------------------------------
/src/utils/USDC/index.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { SUPPORTED_NETWORK } from '@containers/Web3';
5 | import { STABLE_COIN_ADDRESSES } from '@subql/network-config';
6 |
7 | export const STABLE_TOKEN_ADDRESS = STABLE_COIN_ADDRESSES[SUPPORTED_NETWORK];
8 |
--------------------------------------------------------------------------------
/src/utils/colors.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | /**
5 | * NOTE: Any color variable should be align with the index.css and design
6 | * NOTE: Please avoid hardcode any color value in the Page files.
7 | */
8 | export const COLORS = {
9 | primary: '#1677ff',
10 | success: '#65cd45',
11 | error: '#f1585b',
12 |
13 | /*New colors*/
14 | gray200: '#f4f6f8',
15 | gray300: '#dfe3e8',
16 | gray400: '#c4cdd5',
17 | gray500: '#919eab',
18 | gray700: '#454f58',
19 | gray900: '#1a202c',
20 | };
21 |
--------------------------------------------------------------------------------
/src/utils/eip721SignTokenReq.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { FetcherReturnType } from '@graphiql/toolkit';
5 |
6 | export const defaultQuery = `
7 | {
8 | _metadata {
9 | indexerHealthy
10 | indexerNodeVersion
11 | }
12 | }
13 | `;
14 |
15 | export async function fetcher(queryUrl: string, graphqlBody: string, sessionToken: string): Promise {
16 | const headers = {
17 | 'Content-Type': 'application/json',
18 | };
19 | const sortedHeaders = sessionToken ? { ...headers, Authorization: `Bearer ${sessionToken}` } : headers;
20 | const data = await fetch(queryUrl, {
21 | method: 'POST',
22 | headers: sortedHeaders,
23 | body: graphqlBody,
24 | });
25 | return data.json().catch(() => data.text());
26 | }
27 |
--------------------------------------------------------------------------------
/src/utils/eventBus.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import EventEmitter from 'eventemitter3';
5 |
6 | export enum EVENT_TYPE {
7 | CREATED_CONSUMER_OFFER = 'CREATED_CONSUMER_OFFER',
8 | }
9 |
10 | const EventBus = new EventEmitter();
11 |
12 | export { EventBus };
13 |
--------------------------------------------------------------------------------
/src/utils/fetch.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { parseError } from './parseError';
5 |
6 | interface PostProps {
7 | endpoint: string;
8 | headers?: any;
9 | requestBody: any;
10 | }
11 |
12 | interface PostReturn {
13 | response?: Response;
14 | error?: Error | any;
15 | }
16 |
17 | export const POST = async ({ endpoint, headers, requestBody }: PostProps): Promise => {
18 | let response, error;
19 | try {
20 | response = await fetch(endpoint, {
21 | method: 'POST',
22 | headers: { 'Content-Type': 'application/json', ...headers },
23 | body: JSON.stringify(requestBody),
24 | });
25 | } catch (e) {
26 | parseError(e);
27 | error = e;
28 | }
29 |
30 | return { response, error };
31 | };
32 |
33 | export const getAuthReqHeader = (authToken: string): { Authorization: string } => ({
34 | Authorization: `Bearer ${authToken}`,
35 | });
36 |
--------------------------------------------------------------------------------
/src/utils/getFlexPlanPrice.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { BigNumberish } from 'ethers';
5 |
6 | import { convertStringToNumber, formatEther } from './numberFormatters';
7 |
8 | export function getFlexPlanPrice(price: BigNumberish): string {
9 | const amount = 1000;
10 | const sortedPrice = `${convertStringToNumber(formatEther(price, 4)) * amount}`;
11 | const sortedRequest = `${amount} requests`;
12 | return `${sortedPrice} / ${sortedRequest}`;
13 | }
14 |
--------------------------------------------------------------------------------
/src/utils/getIndexerStatus.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { DeploymentStatus } from '@hooks';
5 | import { ServiceStatus } from '@subql/network-query';
6 |
7 | export function getDeploymentStatus(status: ServiceStatus | DeploymentStatus, isOfflineOnContract: boolean): string {
8 | if (status === DeploymentStatus.Unhealthy) {
9 | return DeploymentStatus.Unhealthy;
10 | }
11 | return isOfflineOnContract ? 'OFFLINE' : status;
12 | }
13 |
--------------------------------------------------------------------------------
/src/utils/getOrderedAccounts.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export const getOrderedAccounts = (
5 | accounts: T,
6 | key: K,
7 | targetAccount: string | null | undefined,
8 | ): T => {
9 | if (!targetAccount) return accounts;
10 | return accounts.sort((accountA, accountB) =>
11 | accountA[key] === targetAccount ? -1 : accountB[key] === targetAccount ? 1 : 0,
12 | );
13 | };
14 |
--------------------------------------------------------------------------------
/src/utils/getTrimmedStr.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export const getTrimmedStr = (string: string | undefined, maxLength = 9): string | undefined => {
5 | if (!string) return string;
6 | if (maxLength < 1) return string;
7 | if (string.length <= maxLength) return string;
8 | if (maxLength === 1) return `${string.substring(0, 1)} ...`;
9 |
10 | const midpoint = Math.ceil(string.length / 2);
11 | const toRemove = string.length - maxLength;
12 | const lastRip = Math.ceil(toRemove / 2);
13 | const rstrip = toRemove - lastRip;
14 | return `${string.substring(0, midpoint - lastRip)} ... ${string.substring(midpoint + rstrip)}`;
15 | };
16 |
--------------------------------------------------------------------------------
/src/utils/idleCallback.ts:
--------------------------------------------------------------------------------
1 | export const idleTimeout = (func: () => void) => setTimeout(func, 200);
2 | export const idleCallback = window.requestIdleCallback || idleTimeout;
3 |
4 | export const idleQueue = async (queue: (() => void)[]) => {
5 | const [first, ...rest] = queue;
6 | if (!first) return;
7 | await first();
8 | idleCallback(() => idleQueue(rest));
9 | };
10 |
--------------------------------------------------------------------------------
/src/utils/localStorage.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import CryptoJS from 'crypto-js';
5 |
6 | export const encrypt = (value: string | null, key = 'subquery testnet'): string =>
7 | value ? CryptoJS.DES.encrypt(value, key).toString() : '';
8 | export const decrypt = (value: string | null, key = 'subquery testnet'): string =>
9 | value ? CryptoJS.DES.decrypt(value, key).toString(CryptoJS.enc.Utf8) : '';
10 |
11 | export const setStorage = (key: string, value: string): void => {
12 | localStorage.setItem(key, value);
13 | };
14 |
15 | export const getStorage = (key: string): string | null => {
16 | return localStorage.getItem(key);
17 | };
18 |
19 | export const removeStorage = (key: string): void => {
20 | return localStorage.removeItem(key);
21 | };
22 |
23 | export const setEncryptStorage = (key: string, value: string): void => {
24 | const encryptValue = encrypt(value);
25 | localStorage.setItem(key, encryptValue);
26 | };
27 |
28 | export const getEncryptStorage = (key: string): string => {
29 | return decrypt(localStorage.getItem(key));
30 | };
31 |
--------------------------------------------------------------------------------
/src/utils/retry.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export const retry = (
5 | func: () => void,
6 | options?: {
7 | sleepTime?: number;
8 | retryTime?: number;
9 | },
10 | ) => {
11 | const { sleepTime = 3000, retryTime = 5 } = options || {};
12 | let times = 0;
13 |
14 | const clear = setInterval(() => {
15 | func();
16 | times += 1;
17 | if (times === retryTime) {
18 | clearInterval(clear);
19 | }
20 | }, sleepTime);
21 | };
22 |
--------------------------------------------------------------------------------
/src/utils/stringFormatters.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | export const getCapitalizedStr = (str: string): string => {
5 | return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
6 | };
7 |
--------------------------------------------------------------------------------
/src/utils/useDebounce.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { useEffect, useState } from 'react';
5 |
6 | export function useDebounce(value: T, delay = 5000): T {
7 | const [debouncedValue, setDebouncedValue] = useState(value);
8 | useEffect(() => {
9 | // Update debounced value after delay
10 | const handler = setTimeout(() => {
11 | setDebouncedValue(value);
12 | }, delay);
13 |
14 | return () => {
15 | clearTimeout(handler);
16 | };
17 | }, [value, delay]);
18 | return debouncedValue;
19 | }
20 |
--------------------------------------------------------------------------------
/src/utils/waitForSomething.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { parseError } from '@utils';
5 |
6 | export const sleep = (time = 2000) => new Promise((resolve) => setTimeout(resolve, time));
7 |
8 | interface waitForSomethingArg {
9 | func: () => boolean | PromiseLike;
10 | timeout?: number;
11 | splitTime?: number;
12 | }
13 |
14 | export const waitForSomething = async (
15 | { func, timeout, splitTime = 50 }: waitForSomethingArg,
16 | sleepTime = 0,
17 | ): Promise => {
18 | if (timeout && sleepTime >= timeout) {
19 | return false;
20 | }
21 | try {
22 | const r = await func();
23 |
24 | if (r) {
25 | return r;
26 | }
27 | } catch (e) {
28 | parseError(e);
29 | }
30 |
31 | await sleep(splitTime);
32 |
33 | return waitForSomething({ func, timeout, splitTime }, splitTime + sleepTime);
34 | };
35 |
--------------------------------------------------------------------------------
/src/vite-env.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import 'vite/client';
5 |
6 | declare global {
7 | interface Window {
8 | ethereum?: any;
9 | Buffer?: any;
10 | debugInfo?: any;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2015",
4 | "lib": [
5 | "dom",
6 | "dom.iterable",
7 | "esnext"
8 | ],
9 | "allowJs": true,
10 | "skipLibCheck": true,
11 | "esModuleInterop": true,
12 | "allowSyntheticDefaultImports": true,
13 | "strict": true,
14 | "strictNullChecks": true,
15 | "strictBindCallApply": true,
16 | "strictPropertyInitialization": true,
17 | "forceConsistentCasingInFileNames": true,
18 | "noFallthroughCasesInSwitch": true,
19 | "module": "esnext",
20 | "moduleResolution": "node",
21 | "resolveJsonModule": true,
22 | "isolatedModules": true,
23 | "noEmit": true,
24 | "noImplicitAny": true,
25 | "noImplicitThis": true,
26 | "jsx": "react-jsx",
27 | "plugins": [{ "name": "typescript-plugin-css-modules" }],
28 | "baseUrl": ".",
29 | "paths": {
30 | "@__generated__": ["src/__generated__"],
31 | "@__generated__/*": ["src/__generated__/*"],
32 | "@components": ["./src/components"],
33 | "@components/*": ["./src/components/*"],
34 | "@containers": ["src/containers"],
35 | "@containers/*": ["src/containers/*"],
36 | "@hooks": ["src/hooks"],
37 | "@hooks/*": ["src/hooks/*"],
38 | "@i18n": ["src/i18n"],
39 | "@i18n/*": ["src/i18n/*"],
40 | "@pages": ["src/pages"],
41 | "@pages/*": ["src/pages/*"],
42 | "@utils": ["src/utils"],
43 | "@utils/*": ["src/utils/*"],
44 | }
45 | },
46 | "include": [
47 | "src",
48 | "types",
49 | ],
50 | "exclude": [
51 | "node_modules",
52 | ]
53 | }
54 |
--------------------------------------------------------------------------------
/types/i18next.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | import { GetDictValue, TranslationKeys } from '@i18n';
5 |
6 | import 'i18next';
7 |
8 | // reference: https://www.i18next.com/overview/typescript#argument-of-type-defaulttfuncreturn-is-not-assignable-to-parameter-of-type-xyz
9 | declare module 'i18next' {
10 | interface CustomTypeOptions {
11 | returnNull: false;
12 | // WARNING
13 | // i18next can config this for tips, but it has bug now.
14 | // https://github.com/i18next/i18next/issues/1956 Don't close for now.
15 | // And the declare in typescript is a deep merge. https://www.typescriptlang.org/docs/handbook/declaration-merging.html
16 | // So the TFunction we override will be merge with the default definition.
17 | // The default is `string`, so add a wrong type definition to override the `string`.
18 | // TODO: If the above issue solved will use this instead of override.
19 | resources: { 'z-dont-use-it': '' };
20 | }
21 |
22 | interface TFunction {
23 | (key: T, options?: TOptions): GetDictValue;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/types/react-jazzicon.d.ts:
--------------------------------------------------------------------------------
1 | // Copyright 2020-2022 SubQuery Pte Ltd authors & contributors
2 | // SPDX-License-Identifier: Apache-2.0
3 |
4 | // https://github.com/marcusmolchany/react-jazzicon
5 |
6 | declare module 'react-jazzicon' {
7 | import * as React from 'react';
8 |
9 | type JazziconProps = {
10 | diameter?: number;
11 | paperStyles?: React.CSSProperties;
12 | seed?: number;
13 | svgStyles?: React.CSSProperties;
14 | };
15 |
16 | const Jazzicon: React.FunctionComponent;
17 |
18 | export function jsNumberForAddress(address: string): number;
19 |
20 | export default Jazzicon;
21 | }
22 |
--------------------------------------------------------------------------------