From b4468bcaaa884e9b03d44006fc3d7cc29fd1c3f6 Mon Sep 17 00:00:00 2001 From: cyrbuzz Date: Wed, 27 Dec 2023 16:59:12 +0800 Subject: [PATCH 1/8] feat: change project type --- src/containers/ProjectMetadata.ts | 4 ++-- src/containers/ProjectRegistry.ts | 36 +++--------------------------- src/hooks/useCreateProject.tsx | 5 ++--- src/hooks/useProject.tsx | 1 + src/models.tsx | 2 +- src/pages/studio/Create/Create.tsx | 17 +++++++++----- 6 files changed, 20 insertions(+), 45 deletions(-) diff --git a/src/containers/ProjectMetadata.ts b/src/containers/ProjectMetadata.ts index 2e2dbda4e..f7c860f2a 100644 --- a/src/containers/ProjectMetadata.ts +++ b/src/containers/ProjectMetadata.ts @@ -18,8 +18,8 @@ function useProjectMetadataImpl() { const result = await catSingle(cid); const rawMeta = JSON.parse(Buffer.from(result).toString('utf8')); - console.warn(rawMeta); - return projectMetadataSchema.validate({ type: 'SUBQUERY', ...rawMeta }); + + return projectMetadataSchema.validate({ ...rawMeta }); }; const uploadMetadata = async (meta: ProjectMetadata): Promise => { diff --git a/src/containers/ProjectRegistry.ts b/src/containers/ProjectRegistry.ts index c835355ac..1ca5afebf 100644 --- a/src/containers/ProjectRegistry.ts +++ b/src/containers/ProjectRegistry.ts @@ -12,23 +12,13 @@ import { useWeb3Store } from 'src/stores'; import { bytes32ToCid } from '../utils'; import { createContainer, Logger } from './Container'; -function projectTypeTransform(type: InputProjectType): ProjectType { - switch (type) { - case InputProjectType.SUBQUERY: - return ProjectType.SUBQUERY; - case InputProjectType.RPC: - return ProjectType.RPC; - default: - return ProjectType.SUBQUERY; - } -} - type QueryDetails = { queryId: BigNumber; owner: string; metadata: string; // IPFS Cid deployment: string; // IPFS Cid version: string; // IPFS Cid + type: ProjectType; }; function useProjectRegistryImpl(logger: Logger) { @@ -51,7 +41,7 @@ function useProjectRegistryImpl(logger: Logger) { metadataCid, cidToBytes32(deploymentMetadata), cidToBytes32(deploymentId), - projectTypeTransform(type), + type, ); }; @@ -134,36 +124,16 @@ function useProjectRegistryImpl(logger: Logger) { metadata: uri.replace(/^ipfs:\/\//, ''), deployment: bytes32ToCid(project.latestDeploymentId), version: bytes32ToCid(deploymentInfo.metadata), + type: project.projectType, }; } return projectCache.current[BigNumber.from(id).toString()]; }; - // const getUserQueries = React.useCallback( - // async (address: string): Promise => { - // if (!pendingContracts) { - // throw new Error('ProjectRegistry contract not available'); - // // return []; - // } - - // const contracts = await pendingContracts; - - // const count = await contracts.projectRegistry.queryInfoCountByOwner(address); - - // return await Promise.all( - // Array.from(new Array(count.toNumber()).keys()).map((_, index) => - // contracts.projectRegistry.queryInfoIdsByOwner(address, index), - // ), - // ); - // }, - // [pendingContracts], - // ); - return { registerProject, getQuery, - // getUserQueries, updateQueryMetadata, updateDeployment, }; diff --git a/src/hooks/useCreateProject.tsx b/src/hooks/useCreateProject.tsx index ec3d50ef7..6cf6aa612 100644 --- a/src/hooks/useCreateProject.tsx +++ b/src/hooks/useCreateProject.tsx @@ -3,12 +3,11 @@ import * as React from 'react'; import { BigNumberish } from '@ethersproject/bignumber'; -import { ProjectType } from '@subql/network-query'; import { useIPFS, useProjectMetadata, useProjectRegistry } from '../containers'; -import { FormCreateProjectMetadata, ProjectMetadata } from '../models'; +import { FormCreateProjectMetadata, ProjectMetadata, ProjectType } from '../models'; -type P = FormCreateProjectMetadata & { versionDescription: string }; +type P = FormCreateProjectMetadata & { versionDescription: string; type: ProjectType }; export function useCreateProject(): (params: P) => Promise { const { uploadMetadata, uploadVersionMetadata } = useProjectMetadata(); diff --git a/src/hooks/useProject.tsx b/src/hooks/useProject.tsx index bf13e82e9..41b3164b0 100644 --- a/src/hooks/useProject.tsx +++ b/src/hooks/useProject.tsx @@ -65,6 +65,7 @@ export function useProject(id: string): AsyncData { version: query.version, metadata, deploymentId: query.deployment, + type: query.type, }; }, [id, catSingle, getMetadataFromCid, getQuery, cacheBreak]); } diff --git a/src/models.tsx b/src/models.tsx index 200200dcb..1fd7ebc61 100644 --- a/src/models.tsx +++ b/src/models.tsx @@ -12,7 +12,6 @@ export enum ProjectType { export const projectMetadataSchema = yup.object({ name: yup.string().defined(), - type: yup.string().oneOf(['SUBQUERY', 'RPC'], 'Only RPC and SUBQUERY are allowed.').required(), image: yup.string().optional(), description: yup.string().default('').optional(), websiteUrl: yup.string().optional().url(), @@ -39,6 +38,7 @@ export type ProjectDetails = { metadata: ProjectMetadata; version: string; deploymentId: string; + type: ProjectType; }; export const newDeploymentSchema = yup.object({ diff --git a/src/pages/studio/Create/Create.tsx b/src/pages/studio/Create/Create.tsx index 74bf2aaef..c38bef720 100644 --- a/src/pages/studio/Create/Create.tsx +++ b/src/pages/studio/Create/Create.tsx @@ -14,7 +14,7 @@ import { t } from 'i18next'; import { FTextInput, ImageInput } from '../../../components'; import { useCreateProject, useProject, useRouteQuery, useUpdateProjectMetadata } from '../../../hooks'; -import { FormCreateProjectMetadata, newDeploymentSchema, projectMetadataSchema } from '../../../models'; +import { FormCreateProjectMetadata, newDeploymentSchema, projectMetadataSchema, ProjectType } from '../../../models'; import { categoriesOptions, parseError, ROUTES } from '../../../utils'; import { ProjectDeploymentsDetail } from '../Project/Project'; import styles from './Create.module.less'; @@ -33,7 +33,7 @@ const Create: React.FC = () => { const { getIfUnsafeAndWarn } = useGetIfUnsafeDeployment(); const handleSubmit = React.useCallback( - async (project: FormCreateProjectMetadata & { versionDescription: string }) => { + async (project: FormCreateProjectMetadata & { versionDescription: string; type: ProjectType }) => { try { let resultId = query.get('id'); if (isEdit) { @@ -117,7 +117,7 @@ const Create: React.FC = () => { { versionDescription: '', deploymentId: query.get('deploymentId') ?? '', categories: [], - ...(isEdit ? asyncProject.data?.metadata : {}), + ...(isEdit + ? { + ...asyncProject.data?.metadata, + type: asyncProject.data?.type, + } + : {}), }} validationSchema={ isEdit @@ -234,8 +239,8 @@ const Create: React.FC = () => { }} disabled={isEdit ? true : false} > - SubQuery - RPC + SubQuery + RPC ); }} From 2f66f59fb12966d9528faebf53cbe10d6231a6f8 Mon Sep 17 00:00:00 2001 From: cyrbuzz Date: Thu, 28 Dec 2023 14:57:59 +0800 Subject: [PATCH 2/8] feat: froent end --- .env | 2 +- .env.staging | 2 +- .env.testnet | 2 +- .../AccountActions/AccountActions.module.css | 9 - .../AccountActions/AccountActions.module.less | 43 ++ .../AccountActions/AccountActions.tsx | 168 +++++++- src/components/IndexerDetails/Progress.tsx | 4 +- .../IndexerProgress/IndexerProgress.tsx | 4 +- src/components/Modal/Modal.module.css | 4 - src/components/NumberInput/NumberInput.tsx | 5 +- src/components/TokenTooltip/TokenTooltip.tsx | 47 ++ src/components/TokenTooltip/index.module.less | 9 + src/i18n/en/consumer.ts | 28 +- src/i18n/en/delegator.ts | 6 +- src/i18n/en/explorer.ts | 6 +- src/i18n/en/indexer.ts | 8 +- src/index.less | 7 +- .../CreateOffer/Summary/Summary.module.css | 4 - .../delegator/DoDelegate/DelegateFrom.tsx | 14 +- .../OwnDeployments/OwnDeployments.tsx | 6 +- src/pages/swap/Swap.module.less | 42 -- src/pages/swap/Swap.tsx | 404 ------------------ src/pages/swap/SwapForm.module.less | 58 --- src/pages/swap/SwapForm.tsx | 356 --------------- src/pages/swap/index.ts | 4 - src/router/routes.ts | 1 - src/utils/constants.ts | 2 +- src/utils/links.ts | 4 - 28 files changed, 303 insertions(+), 946 deletions(-) delete mode 100644 src/components/AccountActions/AccountActions.module.css create mode 100644 src/components/AccountActions/AccountActions.module.less create mode 100644 src/components/TokenTooltip/TokenTooltip.tsx create mode 100644 src/components/TokenTooltip/index.module.less delete mode 100644 src/pages/swap/Swap.module.less delete mode 100644 src/pages/swap/Swap.tsx delete mode 100644 src/pages/swap/SwapForm.module.less delete mode 100644 src/pages/swap/SwapForm.tsx delete mode 100644 src/pages/swap/index.ts diff --git a/.env b/.env index 5646d575d..1c5ff054d 100644 --- a/.env +++ b/.env @@ -5,7 +5,7 @@ VITE_QUERY_SWAP_EXCHANGE_PROJECT=https://api.subquery.network/sq/subquery/kepler VITE_TOP_100_INDEXERS=https://leaderboard-api.subquery.network/graphql VITE_CONSUMER_HOST_ENDPOINT=https://kepler-chs.subquery.network VITE_FORUM_DOMAIN=https://forum.subquery.network -VITE_TOKEN=kSQT +VITE_TOKEN=SQT VITE_STABLE_TOKEN=USDC.e VITE_STABLE_TOKEN_ADDRESS=0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 VITE_FLEXPLAN_ENABLED=true diff --git a/.env.staging b/.env.staging index 7efa37c3f..d36f722cb 100644 --- a/.env.staging +++ b/.env.staging @@ -5,7 +5,7 @@ VITE_QUERY_SWAP_EXCHANGE_PROJECT=https://api.subquery.network/sq/subquery/kepler VITE_TOP_100_INDEXERS=https://leaderboard-api.subquery.network/graphql VITE_CONSUMER_HOST_ENDPOINT=https://kepler-chs.subquery.network VITE_FORUM_DOMAIN=https://forum.subquery.network -VITE_TOKEN=kSQT +VITE_TOKEN=SQT VITE_STABLE_TOKEN=USDC.e VITE_STABLE_TOKEN_ADDRESS=0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 VITE_FLEXPLAN_ENABLED=true diff --git a/.env.testnet b/.env.testnet index ee34db3f5..cf17d2094 100644 --- a/.env.testnet +++ b/.env.testnet @@ -3,7 +3,7 @@ VITE_QUERY_REGISTRY_PROJECT=https://api.subquery.network/sq/subquery/kepler-test VITE_SUBSCRIPTION_REGISTRY_PROJECT=wss://api.subquery.network/sq/subquery/kepler-testnet VITE_TOP_100_INDEXERS=https://leaderboard-api.thechaindata.com/graphql VITE_CONSUMER_HOST_ENDPOINT=https://dev-chs.thechaindata.com -VITE_TOKEN=kSQT +VITE_TOKEN=SQT VITE_STABLE_TOKEN=USDC.e VITE_STABLE_TOKEN_ADDRESS=0x7E65A71046170A5b1AaB5C5cC64242EDF95CaBEA VITE_NETWORK=testnet diff --git a/src/components/AccountActions/AccountActions.module.css b/src/components/AccountActions/AccountActions.module.css deleted file mode 100644 index d63845810..000000000 --- a/src/components/AccountActions/AccountActions.module.css +++ /dev/null @@ -1,9 +0,0 @@ -.downIcon { - margin-left: 3px; -} - -.address { - padding: 12px; - border: 1px solid var(--gradient-to); - border-radius: 36px; -} diff --git a/src/components/AccountActions/AccountActions.module.less b/src/components/AccountActions/AccountActions.module.less new file mode 100644 index 000000000..cb352c936 --- /dev/null +++ b/src/components/AccountActions/AccountActions.module.less @@ -0,0 +1,43 @@ +.downIcon { + margin-left: 3px; +} + +.address { + padding: 12px; + border: 1px solid var(--gradient-to); + border-radius: 36px; + display: flex; + align-items: center; + cursor: pointer; +} + +.accountActionDropdown { + width: 380px; + + :global { + .ant-dropdown-menu { + padding: 16px 0; + border-radius: 8px; + box-shadow: 0px 9px 28px 8px rgba(0, 0, 0, 0.05), 0px 6px 16px 0px rgba(0, 0, 0, 0.08), 0px 3px 6px -4px rgba(0, 0, 0, 0.12); + + &-item { + padding: 0!important; + + &:hover { + background-color: transparent!important; + } + } + } + } + + .dropdownItemInner { + padding: 8px 16px; + width: 100%; + display: flex; + align-items: center; + &:hover { + background: rgba(67, 136, 221, 0.10); + } + } +} + diff --git a/src/components/AccountActions/AccountActions.tsx b/src/components/AccountActions/AccountActions.tsx index 6aa9f7b84..d4730fd7c 100644 --- a/src/components/AccountActions/AccountActions.tsx +++ b/src/components/AccountActions/AccountActions.tsx @@ -4,16 +4,17 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { AiOutlineDown } from 'react-icons/ai'; -import { BsBoxArrowLeft } from 'react-icons/bs'; +import { BsBoxArrowInUpRight, BsBoxArrowLeft } from 'react-icons/bs'; import { useNavigate } from 'react-router'; +import { InfoCircleOutlined } from '@ant-design/icons'; import { SQT_TOKEN_ADDRESS } from '@containers/Web3'; -import { Address } from '@subql/components'; +import { Address, Typography } from '@subql/components'; +import { Button, Dropdown, Tooltip } from 'antd'; import { useDisconnect, useWalletClient } from 'wagmi'; import { useSQToken } from '../../containers'; import { formatEther, ROUTES, STABLE_TOKEN, STABLE_TOKEN_ADDRESS, TOKEN, tokenDecimals } from '../../utils'; -import { Dropdown } from '../Dropdown'; -import styles from './AccountActions.module.css'; +import styles from './AccountActions.module.less'; export const AccountActions: React.FC<{ account: string }> = ({ account }) => { const { t } = useTranslation(); @@ -55,24 +56,153 @@ export const AccountActions: React.FC<{ account: string }> = ({ account }) => { }; const menu = [ - { key: 'walletBalance', label: t('header.walletBalance', { balance: formatEther(balance.data, 4) }) }, - { key: 'addToken', label: t('header.importToken'), onClick: handleAddToken }, - { key: 'addStableToken', label: t('header.importStableToken'), onClick: handleAddStableToken }, - { key: 'myProfile', label: t('indexer.myProfile'), onClick: handleNavAccount }, - { key: 'rewards', label: t('indexer.rewards'), onClick: handleNavRewards }, - { key: 'withdrawn', label: t('indexer.withdrawn'), onClick: handleNavWithdrawn }, - { key: 'disconnect', label: t('header.disconnect'), icon: , onClick: handleDisconnect }, + { + key: 'header', + label: ( +
+
+
+ ), + }, + { + key: 'walletBalance', + label: ( +
+
+ + Wallet balance on Polygon + + + {formatEther(balance.data, 4)} {TOKEN} + +
+
+ + Wallet balance on Ethereum + + SubQuery launched on Polygon network, To move assets from the Ethereum network to Polygon network, + you'll need to connect to a bridge and deposit funds. + + } + > + + + + + {formatEther(balance.data, 4)} {TOKEN} + +
+
+ ), + }, + { + key: 'bridge tokens', + label: ( +
+ +
+ ), + }, + { + key: 'billingBalance', + label: ( +
+
+ Billing Balance: + 200 {TOKEN} +
+ + View Details +
+ ), + }, + { + key: 'addTokens', + label: ( +
+
+ {t('header.importToken')} +
+
+ {t('header.importStableToken')} +
+
+ ), + }, + { + key: 'myProfile', + label: ( +
+
+ {t('indexer.myProfile')} +
+
+ {t('indexer.rewards')} +
+
+ {t('indexer.withdrawn')} +
+
+ ), + }, + { + key: 'disconnect', + label: ( +
+
+ {t('header.disconnect')} +
+
+ ), + }, ]; return ( -
- - - } - /> + overlayClassName={styles.accountActionDropdown} + menu={{ items: menu }} + placement="bottom" + arrow={{ pointAtCenter: true }} + > +
+
+ +
+ ); }; diff --git a/src/components/IndexerDetails/Progress.tsx b/src/components/IndexerDetails/Progress.tsx index a3528dfba..99238581c 100644 --- a/src/components/IndexerDetails/Progress.tsx +++ b/src/components/IndexerDetails/Progress.tsx @@ -3,7 +3,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; -import { ProgressBar, Typography } from '@subql/components'; +import { SubqlProgress, Typography } from '@subql/components'; import { indexingProgress } from '@subql/network-clients'; import { strip } from '@utils'; @@ -33,7 +33,7 @@ const Progress: React.FC<{ startBlock?: number; currentBlock: number; targetBloc return (
- + {blocksBehind > 0 && (
diff --git a/src/components/IndexerProgress/IndexerProgress.tsx b/src/components/IndexerProgress/IndexerProgress.tsx index 42766c616..a21b0f1b9 100644 --- a/src/components/IndexerProgress/IndexerProgress.tsx +++ b/src/components/IndexerProgress/IndexerProgress.tsx @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import * as React from 'react'; -import { ProgressBar } from '@subql/components'; +import { SubqlProgress } from '@subql/components'; import styles from './IndexerProgress.module.css'; @@ -40,7 +40,7 @@ const IndexerProgress: React.FC = ({ indexerStatus, chainBlockHeight, sta return (
{status} - +
); }; diff --git a/src/components/Modal/Modal.module.css b/src/components/Modal/Modal.module.css index 5d0380d4f..c18537e7f 100644 --- a/src/components/Modal/Modal.module.css +++ b/src/components/Modal/Modal.module.css @@ -1,7 +1,3 @@ -.steps { - margin: 0 0 1.25rem 0; -} - .title { font-weight: 600; } diff --git a/src/components/NumberInput/NumberInput.tsx b/src/components/NumberInput/NumberInput.tsx index a37a125ac..cf6ae6854 100644 --- a/src/components/NumberInput/NumberInput.tsx +++ b/src/components/NumberInput/NumberInput.tsx @@ -4,6 +4,7 @@ import * as React from 'react'; import { useMemo } from 'react'; import { Typography } from '@subql/components'; +import { TOKEN } from '@utils'; import { Button, InputNumber, InputNumberProps } from 'antd'; import BigNumber from 'bignumber.js'; import { BigNumberish } from 'ethers'; @@ -21,13 +22,13 @@ interface NumberInputProps extends InputNumberProps { errorMsg?: string; onClickMax?: (amount: number | BigNumberish) => void; maxAmount?: number | BigNumberish; - maxAmountText?: string; + maxAmountText?: React.ReactNode; } export const NumberInput: React.FC = ({ title, tooltip, - unit = 'kSQT', + unit = TOKEN, maxAmountText, maxAmount = 0, onClickMax, diff --git a/src/components/TokenTooltip/TokenTooltip.tsx b/src/components/TokenTooltip/TokenTooltip.tsx new file mode 100644 index 000000000..8d19221b8 --- /dev/null +++ b/src/components/TokenTooltip/TokenTooltip.tsx @@ -0,0 +1,47 @@ +// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import React, { FC } from 'react'; +import { ExclamationCircleFilled, InfoCircleOutlined } from '@ant-design/icons'; +import { Typography } from '@subql/components'; +import { TOKEN } from '@utils'; +import { Button, Tooltip } from 'antd'; + +import styles from './index.module.less'; + +interface IProps { + children?: React.ReactNode; +} + +const TokenTooltip: FC = (props) => { + return ( + +
+ + You have {TOKEN} on Ethereum +
+ + Eth Wallet Balance: {TOKEN} + + + Your SQT needs to be on Polygon in order to be used on the SubQuery Network. To move SQT from the Ethereum + to Polygon, you’ll need to bridge them across. + + +
+ +
+
+ } + > + {props.children ? props.children : } + + ); +}; +export default TokenTooltip; diff --git a/src/components/TokenTooltip/index.module.less b/src/components/TokenTooltip/index.module.less new file mode 100644 index 000000000..99f77ede6 --- /dev/null +++ b/src/components/TokenTooltip/index.module.less @@ -0,0 +1,9 @@ +.tokenTooltip { + + :global { + .ant-tooltip-inner { + padding: 16px; + width: 305px; + } + } +} \ No newline at end of file diff --git a/src/i18n/en/consumer.ts b/src/i18n/en/consumer.ts index ad1f76706..5f2582e64 100644 --- a/src/i18n/en/consumer.ts +++ b/src/i18n/en/consumer.ts @@ -121,20 +121,20 @@ const translation = { playground: 'Playground', error: 'Fetch playground wrong', billing: { - transfer: `Transfer ${TOKEN ?? 'kSQT'} to billing account`, - addToken: `Add ${TOKEN ?? 'kSQT'}`, + transfer: `Transfer ${TOKEN ?? 'SQT'} to billing account`, + addToken: `Add ${TOKEN ?? 'SQT'}`, confirmTransfer: 'Confirm Transfer', transferDescription: `When transferring ${TOKEN} you are also authorising SubQuery to perform some automated tasks on your behalf. For example: topping up your Flex Plans that are running low on funds or terminating a channel if the Indexer requests it to be closed. This automation will prevent delays and give you the best user experience.`, - transferToken: `Transfer ${TOKEN ?? 'kSQT'}`, - failureTransfer: `Sorry, failed to transfer ${TOKEN ?? 'kSQT'}`, - successTransfer: `You have successfully transferred ${TOKEN ?? 'kSQT'}`, + transferToken: `Transfer ${TOKEN ?? 'SQT'}`, + failureTransfer: `Sorry, failed to transfer ${TOKEN ?? 'SQT'}`, + successTransfer: `You have successfully transferred ${TOKEN ?? 'SQT'}`, notEnoughToken: `You don't have enough ${TOKEN} in your wallet.`, - withdrawTitle: `Withdraw ${TOKEN ?? 'kSQT'} to wallet`, - withdraw: `Withdraw ${TOKEN ?? 'kSQT'} to wallet`, - withdrawToken: `Withdraw ${TOKEN ?? 'kSQT'}`, + withdrawTitle: `Withdraw ${TOKEN ?? 'SQT'} to wallet`, + withdraw: `Withdraw ${TOKEN ?? 'SQT'} to wallet`, + withdrawToken: `Withdraw ${TOKEN ?? 'SQT'}`, confirmWithdraw: 'Confirm withdraw', - failureWithdraw: `Sorry, failed to withdraw ${TOKEN ?? 'kSQT'}`, - successWithdraw: `You have successfully withdrawn ${TOKEN ?? 'kSQT'}`, + failureWithdraw: `Sorry, failed to withdraw ${TOKEN ?? 'SQT'}`, + successWithdraw: `You have successfully withdrawn ${TOKEN ?? 'SQT'}`, }, claim: { title: 'Claim remaining deposit', @@ -343,11 +343,11 @@ const translation = { }, }, swap: { - buykSQT: `${STABLE_TOKEN} → ${TOKEN}`, - sellkSQT: `${TOKEN} → ${STABLE_TOKEN}`, + buySQT: `${STABLE_TOKEN} → ${TOKEN}`, + sellSQT: `${TOKEN} → ${STABLE_TOKEN}`, poolSize: `${TOKEN} pool size`, nonOrder: `There is no available order in pool currently. `, - nonOrderDesc: `Currently, there are no active swap orders available. However, don't worry - when orders become available, you can convert between USDC and kSQT using our basic swap mechanism. Get ready to swap with Kepler!`, + nonOrderDesc: `Currently, there are no active swap orders available. However, don't worry - when orders become available, you can convert between USDC and SQT using our basic swap mechanism. Get ready to swap with Kepler!`, poolSizeTooltip: `This is the amount of ${TOKEN} currently available to be purchased in the liquidity pool`, curRate: 'current rate', curRateTooltip: 'The token rate will remain fixed in Kepler network before mainnet is launched', @@ -366,7 +366,7 @@ const translation = { swapSuccess: 'The swap transaction has succeeded.', swapFailure: 'The transaction has failed.', usdcLimitation: - 'The maximum amount of USDC that you can swap to kSQT in a single transaction is {{limitation}}. Please decrease your order size', + 'The maximum amount of USDC that you can swap to SQT in a single transaction is {{limitation}}. Please decrease your order size', }, } as const; diff --git a/src/i18n/en/delegator.ts b/src/i18n/en/delegator.ts index 9deeb1b94..323d23390 100644 --- a/src/i18n/en/delegator.ts +++ b/src/i18n/en/delegator.ts @@ -29,8 +29,8 @@ const translation = { delegateSuccess: 'Success! Your delegation has been completed.', approveTokenToDelegate: 'Approve your token for staking', nonDelegating: `You haven’t delegated to any Indexers yet`, - nonDelegatingDesc1: `You can participate in the SubQuery network as a Delegator by allocating your kSQT tokens to indexers of your choice.`, - nonDelegatingDesc2: `Delegators help the network to become more transparent and secure. In return, you earn rewards in kSQT from the reward pool.`, + nonDelegatingDesc1: `You can participate in the SubQuery network as a Delegator by allocating your SQT tokens to indexers of your choice.`, + nonDelegatingDesc2: `Delegators help the network to become more transparent and secure. In return, you earn rewards in SQT from the reward pool.`, yourDelegateAmount: 'Your Delegation Amount', none: 'No Delegator available', viewProfile: 'View Indexer Profile', @@ -40,7 +40,7 @@ const translation = { invalidUndelegateBeforeRewardCollect: `This Indexer cannot be undelegated from until they collect all the early era's rewards. Please contact the indexer to resolve the issue.`, nonToUndelegate: `There is 0 ${TOKEN} delegating for next era.`, delegationDesc: - 'View all Indexers you have delegated your kSQT tokens to. In return for delegating, you will earn rewards in kSQT from the rewards pool.', + 'View all Indexers you have delegated your SQT tokens to. In return for delegating, you will earn rewards in SQT from the rewards pool.', walletBalance: 'Wallet Balance: {{balance}} {{token}}', amountAvailable: 'Amount available for re-delegation: {{balance}} {{token}}', remainingCapacity: 'Remaining Delegation Capacity', diff --git a/src/i18n/en/explorer.ts b/src/i18n/en/explorer.ts index 569c6c5a2..c8110ca03 100644 --- a/src/i18n/en/explorer.ts +++ b/src/i18n/en/explorer.ts @@ -46,10 +46,10 @@ const translation = { withdrawn: 'Withdrawn', }, tooltip: { - delegating: 'The amount of kSQT that you are delegating to Indexers in the SubQuery Network to earn rewards', - staking: 'The amount of kSQT that you have staked against projects you are indexing in the SubQuery Network', + delegating: 'The amount of SQT that you are delegating to Indexers in the SubQuery Network to earn rewards', + staking: 'The amount of SQT that you have staked against projects you are indexing in the SubQuery Network', rewards: 'The amount of rewards earned by participating in the SubQuery Network through delegating or staking', - withdrawn: 'The amount of kSQT that you have undelegated or unstaked', + withdrawn: 'The amount of SQT that you have undelegated or unstaked', }, linkText: { delegating: 'Delegate to an Indexer', diff --git a/src/i18n/en/indexer.ts b/src/i18n/en/indexer.ts index 69480d051..bf5f3bfd2 100644 --- a/src/i18n/en/indexer.ts +++ b/src/i18n/en/indexer.ts @@ -64,7 +64,7 @@ const translation = { doStake: 'You haven’t staked yet. Stake to become an indexer.', doStakeTitle: 'Start staking now to earn as an Indexer', doStakeDesc: - 'In order to earn rewards from query revenue, Indexers must stake kSQT against a particular SubQuery Project that they are providing the service to.', + 'In order to earn rewards from query revenue, Indexers must stake SQT against a particular SubQuery Project that they are providing the service to.', learnMore: 'Learn how to become an Indexer <1>here<1>', topRowData: 'Top row of the data represents the data in current era.', secondRowData: 'Data displayed after means the data that will take into effect from next era.', @@ -103,7 +103,7 @@ const translation = { myDelegators: { noDelegatorsTitle: 'You don’t have any Delegators yet', noDelegatorsDescription: - 'Once Delegators have delegated their kSQT to you, they will appear here. First you need to register as an Indexer and begin indexing SubQuery projects, Delegators can then delegate their kSQT to you to earn rewards. Delegators are more likely to delegate their kSQT to high performing Indexers and Consumers will be attracted to Indexers with more kSQT delegated as it indicates they are reliable.', + 'Once Delegators have delegated their SQT to you, they will appear here. First you need to register as an Indexer and begin indexing SubQuery projects, Delegators can then delegate their SQT to you to earn rewards. Delegators are more likely to delegate their SQT to high performing Indexers and Consumers will be attracted to Indexers with more SQT delegated as it indicates they are reliable.', noDelegatorsInfoLink: 'Learn more about Delegators ', }, tokenApproval: { @@ -121,7 +121,7 @@ const translation = { failureCollect: 'Sorry, collect rewards transaction has failed.', }, topIndexers: { - desc: 'View the top 100 ranked Indexers and all other Indexers in the SubQuery Network and delegate your kSQT tokens to earn rewards.', + desc: 'View the top 100 ranked Indexers and all other Indexers in the SubQuery Network and delegate your SQT tokens to earn rewards.', nonData: 'There is no data to display', rank: 'indexer rank', uptime: 'uptime', @@ -151,7 +151,7 @@ const translation = { }, allIndexers: { nonData: 'There is no Indexer available.', - desc: 'View all Indexers in the SubQuery Network and delegate your kSQT tokens to earn rewards.', + desc: 'View all Indexers in the SubQuery Network and delegate your SQT tokens to earn rewards.', }, } as const; diff --git a/src/index.less b/src/index.less index 8a414eec0..86308695c 100644 --- a/src/index.less +++ b/src/index.less @@ -298,4 +298,9 @@ label, .staticButton.ant-btn-primary { background-color: rgba(67, 136, 221, 0.10); color: var(--sq-blue600); -} \ No newline at end of file +} + +.ant-btn-primary.ant-btn-background-ghost { + border-color: var(--sq-blue600); + color: var(--sq-blue600); +} diff --git a/src/pages/consumer/MyOffers/CreateOffer/Summary/Summary.module.css b/src/pages/consumer/MyOffers/CreateOffer/Summary/Summary.module.css index 3eb49e26f..d5b5d8d86 100644 --- a/src/pages/consumer/MyOffers/CreateOffer/Summary/Summary.module.css +++ b/src/pages/consumer/MyOffers/CreateOffer/Summary/Summary.module.css @@ -5,10 +5,6 @@ padding: 1rem; } -.steps { - margin: 1rem 0; -} - .tabs { display: flex; justify-content: space-between; diff --git a/src/pages/delegator/DoDelegate/DelegateFrom.tsx b/src/pages/delegator/DoDelegate/DelegateFrom.tsx index e2d7763e6..4f5493652 100644 --- a/src/pages/delegator/DoDelegate/DelegateFrom.tsx +++ b/src/pages/delegator/DoDelegate/DelegateFrom.tsx @@ -5,6 +5,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { BsExclamationCircle } from 'react-icons/bs'; import { useNavigate } from 'react-router'; +import TokenTooltip from '@components/TokenTooltip/tokenTooltip'; import { useFetchMetadata } from '@hooks/useFetchMetadata'; import { Typography } from '@subql/components'; import { useGetDelegationQuery, useGetDelegationsLazyQuery } from '@subql/react-hooks'; @@ -123,10 +124,15 @@ export const DelegateForm: React.FC = ({ const maxAmountText = React.useMemo(() => { if (isYourself) { - return t('delegate.walletBalance', { - balance: formatEther(balance.data, 4), - token: TOKEN, - }); + return ( + <> + {t('delegate.walletBalance', { + balance: formatEther(balance.data, 4), + token: TOKEN, + })}{' '} + + + ); } return t('delegate.amountAvailable', { balance: sortedMaxAmount, diff --git a/src/pages/indexer/MyProjects/OwnDeployments/OwnDeployments.tsx b/src/pages/indexer/MyProjects/OwnDeployments/OwnDeployments.tsx index 5df45cfb2..010e126a8 100644 --- a/src/pages/indexer/MyProjects/OwnDeployments/OwnDeployments.tsx +++ b/src/pages/indexer/MyProjects/OwnDeployments/OwnDeployments.tsx @@ -4,7 +4,7 @@ import * as React from 'react'; import { useTranslation } from 'react-i18next'; import { useNavigate } from 'react-router-dom'; -import { ProgressBar, Spinner } from '@subql/components'; +import { Spinner, SubqlProgress } from '@subql/components'; import { TableTitle } from '@subql/components'; import { getDeploymentStatus } from '@utils/getIndexerStatus'; import { Table, TableProps, Typography } from 'antd'; @@ -51,7 +51,9 @@ export const OwnDeployments: React.FC = ({ indexer, emptyList, desc }) => {indexingProgressErr}
); - return ; + return ( + + ); }, }, { diff --git a/src/pages/swap/Swap.module.less b/src/pages/swap/Swap.module.less deleted file mode 100644 index 87c7cc7f2..000000000 --- a/src/pages/swap/Swap.module.less +++ /dev/null @@ -1,42 +0,0 @@ -.swap { - display: flex; - background-color: var(--gray100); - flex-direction: column; - width: 100%; -} - -.container { - margin: auto; - width: 60%; - display: flex; -} - -.content { - min-height: 60vh; - width: 100%; - background: white; - border-radius: 8px; - padding: 2rem; -} - -.tabs { - display: flex; - justify-content: center; - align-items: center; - - :global { - .tabButtons { - width: auto; - } - } -} - -.dataUpdateText { - font-size: 16px; - margin: 1rem; -} - -.footer { - position: relative; - bottom: -2rem; -} diff --git a/src/pages/swap/Swap.tsx b/src/pages/swap/Swap.tsx deleted file mode 100644 index 721530ec1..000000000 --- a/src/pages/swap/Swap.tsx +++ /dev/null @@ -1,404 +0,0 @@ -// Copyright 2020-2022 SubQuery Pte Ltd authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -import * as React from 'react'; -import { useTranslation } from 'react-i18next'; -import { BsExclamationTriangle } from 'react-icons/bs'; -import { Navigate, Route, Routes } from 'react-router'; -import { ApproveContract, EmptyList, Spinner, TabButtons, WalletRoute } from '@components'; -import { useSQToken, useWeb3 } from '@containers'; -import { SQT_TOKEN_ADDRESS } from '@containers/Web3'; -import { useAirdropKyc } from '@hooks/useAirdropKyc'; -import { useAUSDAllowance, useAUSDBalance, useAUSDContract, useAUSDTotalSupply } from '@hooks/useASUDContract'; -import { - useSellSQTQuota, - useSwapOrderId, - useSwapPool, - useSwapRate, - useSwapToken, - useSwapTradeLimitation, -} from '@hooks/useSwapData'; -import { Footer, openNotification, Typography as SubqlTypography } from '@subql/components'; -import { - formatEther, - mergeAsync, - parseError, - renderAsyncArray, - ROUTES, - STABLE_TOKEN, - STABLE_TOKEN_ADDRESS, - STABLE_TOKEN_DECIMAL, - TOKEN, -} from '@utils'; -import { limitContract } from '@utils/limitation'; -import { makeCacheKey } from '@utils/limitation'; -import { Typography } from 'antd'; -import { BigNumber, BigNumberish } from 'ethers'; -import { formatUnits } from 'ethers/lib/utils'; -import i18next, { TFunction } from 'i18next'; - -import { useWeb3Store } from 'src/stores'; - -import styles from './Swap.module.less'; -import { SwapForm } from './SwapForm'; - -const { SWAP, SELL, BUY } = ROUTES; - -const buttonLinks = [ - { label: i18next.t('swap.buykSQT'), link: `${SWAP}/${BUY}` }, - { label: i18next.t('swap.sellkSQT'), link: `${SWAP}/${SELL}` }, -]; - -const getStats = ({ - sqtPoolSize, - swappableBalance, - sqtAUSDRate, - tokenGet, - tokenGive, - t, -}: { - sqtPoolSize?: BigNumberish; - swappableBalance?: BigNumberish; - tokenGet: string; - tokenGive: string; - sqtAUSDRate: number; - t: TFunction; -}) => { - const curRateStats = { - title: t('swap.curRate'), - value: sqtAUSDRate > 0 ? `1 ${tokenGet} = ${sqtAUSDRate} ${tokenGive}` : '-', - tooltip: t('swap.curRateTooltip'), - }; - - if (sqtPoolSize) { - return [ - { - title: t('swap.poolSize'), - value: `${sqtPoolSize} ${TOKEN}`, - tooltip: t('swap.poolSizeTooltip'), - }, - curRateStats, - ]; - } - - return [ - { - title: t('swap.swappableBalance'), - value: `${swappableBalance ?? 0} ${TOKEN}`, - tooltip: t('swap.swappableBalanceTooltip'), - }, - curRateStats, - ]; -}; - -const useGetUSDCTradeLimitation = () => { - const { account } = useWeb3(); - const { contracts } = useWeb3Store(); - const aUSDBalance = useAUSDBalance(); - const totalLimitation = useSwapTradeLimitation(); - const [maxTradelimitation, setMaxTradeLimitation] = React.useState(0); - const [leftTradeAmount, setLeftTradeAmount] = React.useState(0); - const [totalTradeAmountUser, setTotalTradeAmountUser] = React.useState(0); - const initMaxTradeLimitation = async () => { - try { - if (!aUSDBalance.data || !contracts || !account) return 0; - // returned values are USDC - const tradeLimitationPerAccount = - (await limitContract( - () => contracts.permissionedExchange.tradeLimitationPerAccount(), - makeCacheKey(account, { type: 'perAccountTrade' }), - )) || BigNumber.from(0); - const accumulatedTrades = - (await limitContract( - () => contracts.permissionedExchange.accumulatedTrades(account), - makeCacheKey(account, { type: 'accumulated' }), - )) || BigNumber.from(0); - - const tradeLimitation = totalLimitation.data || BigNumber.from(0); - - const formatedTradeLimitation = formatUnits(tradeLimitation, STABLE_TOKEN_DECIMAL); - const formtedTradelimitationPerAccount = formatUnits(tradeLimitationPerAccount, STABLE_TOKEN_DECIMAL); - const formatedAccumulatedTrades = formatUnits(accumulatedTrades, STABLE_TOKEN_DECIMAL); - setLeftTradeAmount(+formtedTradelimitationPerAccount - +formatedAccumulatedTrades); - setTotalTradeAmountUser(+formtedTradelimitationPerAccount); - return Math.min( - +aUSDBalance.data, - +formatedTradeLimitation, - +formtedTradelimitationPerAccount - +formatedAccumulatedTrades, - ); - } catch (e) { - console.warn(e); - openNotification({ - type: 'error', - description: 'Fetch trade limitation failed, please change your RPC Endpoint and try again.', - }); - - return 0; - } - }; - - const init = async () => { - const res = await initMaxTradeLimitation(); - - setMaxTradeLimitation(res); - }; - - React.useEffect(() => { - init(); - }, [account, aUSDBalance.data, totalLimitation.data, contracts]); - - return { maxTradelimitation, leftTradeAmount, totalTradeAmountUser, refresh: init }; -}; - -const USDCToSqt = () => { - const { t } = useTranslation(); - const { account } = useWeb3(); - const [kycStatus, setKycStatus] = React.useState(false); - const { maxTradelimitation, leftTradeAmount, totalTradeAmountUser, refresh } = useGetUSDCTradeLimitation(); - const aUSDContract = useAUSDContract(); - const aUSDAllowance = useAUSDAllowance(); - const requireTokenApproval = aUSDAllowance?.data?.isZero(); - const { orderId, loading: fetchingOrderId } = useSwapOrderId(SQT_TOKEN_ADDRESS ?? ''); - - const swapRate = useSwapRate(orderId); - const swapPool = useSwapPool(orderId); - const swapTokens = useSwapToken(orderId); - const aUSDBalance = useAUSDBalance(); - const aUSDTotalSupply = useAUSDTotalSupply(); - const usdcToSqtLimitation = useSwapTradeLimitation(); - const { getKycStatus } = useAirdropKyc(); - - const initKyc = async (address: string) => { - const res = await getKycStatus(address); - setKycStatus(res); - }; - - React.useEffect(() => { - setKycStatus(false); - if (account) { - initKyc(account); - } - }, [account, aUSDBalance.data]); - - if (fetchingOrderId) return ; - - if (!orderId) return ; - - return renderAsyncArray( - mergeAsync(swapRate, swapPool, swapTokens, aUSDBalance, aUSDTotalSupply, usdcToSqtLimitation), - { - error: (error) => { - return {`Failed to load info: ${parseError(error) || ''}`}; - }, - empty: () => {`There is no data available`}, - data: (data) => { - const [sqtAUSDRate, sqtPoolSize, tokens, _, aUSDSupply, usdcToSqtLimitation] = data; - if (sqtAUSDRate === undefined || sqtPoolSize === undefined || fetchingOrderId) return ; - - // const sortedAUSDBalance = aUSDAmount ?? '0'; - const sortedRate = sqtAUSDRate ?? 0; - const sortedPoolSize = sqtPoolSize ?? '0'; - const pair = { - from: STABLE_TOKEN, - fromMax: maxTradelimitation.toString(), - to: TOKEN, - toMax: formatEther(sortedPoolSize), - }; - - const stats = getStats({ - sqtPoolSize: formatEther(sortedPoolSize, 4), - sqtAUSDRate: sortedRate, - tokenGet: tokens?.tokenGet ?? '', - tokenGive: tokens?.tokenGive ?? '', - t, - }); - - return ( - <> - {!kycStatus && ( -
- - -
- - Only participants that have been KYC’d and whitelisted can participate in the SubQuery Kepler Swap. - You can see a list of all existing whitelisted participants{' '} - - here - - . - - - If you’re new here, check out{' '} - - this article - {' '} - and follow the instructions on how to join. - - - If you need any help, you can reach out on the #kepler-swap-support channel in our{' '} - - Discord - - . - -
-
- )} - aUSDAllowance?.refetch()} - increaseAllowanceAmount={aUSDSupply} - onUpdateSwapData={() => { - swapTokens.refetch(true); - swapPool.refetch(true); - aUSDBalance.refetch(true); - refresh(); - }} - kycStatus={kycStatus} - lifetimeLimitationInfo={{ - isOut: leftTradeAmount === 0, - limitation: totalTradeAmountUser, - }} - /> - - ); - }, - }, - ); -}; - -// TODO: Improve useSwapToken function: as current use TOKEN in util / useSwapToken two places -const SqtToUSDC = () => { - const { t } = useTranslation(); - const { account } = useWeb3(); - const { permissionExchangeAllowance } = useSQToken(); - const requireTokenApproval = permissionExchangeAllowance?.data?.isZero(); - - const { orderId, loading: fetchingOrderId } = useSwapOrderId(STABLE_TOKEN_ADDRESS ?? ''); - - const swapRate = useSwapRate(orderId); - const swapTokens = useSwapToken(orderId); - const tradableQuota = useSellSQTQuota(account ?? ''); - const { balance } = useSQToken(); - const aUSDBalance = useAUSDBalance(); - - if (fetchingOrderId) return ; - - if (!orderId) return ; - - return renderAsyncArray(mergeAsync(swapRate, tradableQuota, swapTokens, balance, aUSDBalance), { - error: (error) => ( - - {t('errors.failedToGetIndexerInfo', { message: parseError(error) || '' })} - - ), - empty: () => {`There is no data available`}, - data: (data) => { - const [swapRate, tradeQuota, tokens, sqtBalance, aUSDAmount] = data; - - if (aUSDAmount === undefined || swapRate === undefined || fetchingOrderId) return ; - - const sortedBalance = sqtBalance ?? BigNumber.from('0'); - const sortedRate = swapRate ?? 0; - const sortedPoolSize = tradeQuota ?? BigNumber.from('0'); - - const fromMax = sortedBalance.gt(sortedPoolSize) ? tradeQuota : sortedBalance; - const toMax = aUSDAmount ?? '0'; - - const pair = { - from: TOKEN, - fromMax: formatEther(fromMax), - to: STABLE_TOKEN, - toMax, - }; - - const stats = getStats({ - swappableBalance: formatEther(tradeQuota, 4), - sqtAUSDRate: sortedRate, - tokenGet: tokens?.tokenGet ?? '', - tokenGive: tokens?.tokenGive ?? '', - t, - }); - - const leftOrderAmount = tokens?.leftTokenGiveBalance; - - return ( - requireTokenApproval && permissionExchangeAllowance.refetch()} - contract={ApproveContract.PermissionedExchange} - onUpdateSwapData={() => { - swapTokens.refetch(true); - balance.refetch(true); - aUSDBalance.refetch(true); - tradableQuota.refetch(true); - }} - leftOrdersAmountInfo={{ - isOut: !!leftOrderAmount?.eq(0), - leftOrderAmount: leftOrderAmount || BigNumber.from(0), - }} - kycStatus - /> - ); - }, - }); -}; - -const Swap: React.FC = () => { - return ( - -
-
-
- -
- - } /> - } /> - } /> - -
-
- -