diff --git a/src/canvas/JoinPool/Header.tsx b/src/canvas/JoinPool/Header.tsx index 93109708a9..2af9044820 100644 --- a/src/canvas/JoinPool/Header.tsx +++ b/src/canvas/JoinPool/Header.tsx @@ -25,6 +25,7 @@ export const Header = ({ autoSelected, setActiveTab, setSelectedPoolId, + providedPoolId, }: JoinPoolHeaderProps) => { const { t } = useTranslation(); const { closeCanvas } = useOverlay().canvas; @@ -44,12 +45,14 @@ export const Header = ({ return ( <>
- handleChooseNewPool()} - lg - /> + {providedPoolId === null && ( + handleChooseNewPool()} + lg + /> + )} {

- {targets.length}{' '} {!targets.length ? t('nominate.noNominationsSet', { ns: 'pages' }) - : ``}{' '} - {t('nominations', { ns: 'library', count: targets.length })} + : `${targets.length} ${t('nominations', { ns: 'library', count: targets.length })}`}

- - {targets.length > 0 ? ( - - ) : ( -

{t('poolIsNotNominating', { ns: 'modals' })}

- )} -
+ + {targets.length > 0 && ( + + )}
); }; diff --git a/src/canvas/JoinPool/Overview/PerformanceGraph.tsx b/src/canvas/JoinPool/Overview/PerformanceGraph.tsx index f2562b61ee..910c3f7b12 100644 --- a/src/canvas/JoinPool/Overview/PerformanceGraph.tsx +++ b/src/canvas/JoinPool/Overview/PerformanceGraph.tsx @@ -39,14 +39,17 @@ ChartJS.register( Legend ); -export const PerformanceGraph = ({ bondedPool }: OverviewSectionProps) => { +export const PerformanceGraph = ({ + bondedPool, + performanceKey, +}: OverviewSectionProps) => { const { t } = useTranslation(); const { mode } = useTheme(); const { openHelp } = useHelp(); const { colors } = useNetwork().networkData; const { getPoolRewardPoints } = usePoolPerformance(); - const poolRewardPoints = getPoolRewardPoints('pool_join'); + const poolRewardPoints = getPoolRewardPoints(performanceKey); const rawEraRewardPoints = poolRewardPoints[bondedPool.addresses.stash] || {}; // Ref to the graph container. diff --git a/src/canvas/JoinPool/Overview/Stats.tsx b/src/canvas/JoinPool/Overview/Stats.tsx index 5281c2debd..198991e83a 100644 --- a/src/canvas/JoinPool/Overview/Stats.tsx +++ b/src/canvas/JoinPool/Overview/Stats.tsx @@ -9,8 +9,10 @@ import BigNumber from 'bignumber.js'; import { useEffect, useState } from 'react'; import type { OverviewSectionProps } from '../types'; import { useTranslation } from 'react-i18next'; +import { usePoolPerformance } from 'contexts/Pools/PoolPerformance'; +import { MaxEraRewardPointsEras } from 'consts'; -export const Stats = ({ bondedPool }: OverviewSectionProps) => { +export const Stats = ({ bondedPool, performanceKey }: OverviewSectionProps) => { const { t } = useTranslation('library'); const { networkData: { @@ -20,6 +22,11 @@ export const Stats = ({ bondedPool }: OverviewSectionProps) => { }, } = useNetwork(); const { isReady, api } = useApi(); + const { getPoolRewardPoints } = usePoolPerformance(); + const poolRewardPoints = getPoolRewardPoints(performanceKey); + const rawEraRewardPoints = Object.values( + poolRewardPoints[bondedPool.addresses.stash] || {} + ); // Store the pool balance. const [poolBalance, setPoolBalance] = useState(null); @@ -52,7 +59,9 @@ export const Stats = ({ bondedPool }: OverviewSectionProps) => { return (

- {t('activelyNominating')} + {rawEraRewardPoints.length === MaxEraRewardPointsEras && ( + {t('activelyNominating')} + )} diff --git a/src/canvas/JoinPool/Overview/index.tsx b/src/canvas/JoinPool/Overview/index.tsx index 107a5b7ed9..57bef1f426 100644 --- a/src/canvas/JoinPool/Overview/index.tsx +++ b/src/canvas/JoinPool/Overview/index.tsx @@ -9,21 +9,39 @@ import { Addresses } from './Addresses'; import { Roles } from './Roles'; import { GraphLayoutWrapper } from '../Wrappers'; import type { OverviewSectionProps } from '../types'; +import { useBalances } from 'contexts/Balances'; +import { useActiveAccounts } from 'contexts/ActiveAccounts'; -export const Overview = (props: OverviewSectionProps) => ( - <> -
- - - - - - -
-
-
- +export const Overview = (props: OverviewSectionProps) => { + const { getPoolMembership } = useBalances(); + const { activeAccount } = useActiveAccounts(); + + const { + bondedPool: { state }, + } = props; + + const showJoinForm = + activeAccount !== null && + state === 'Open' && + getPoolMembership(activeAccount) === null; + + return ( + <> +
+ + + + + +
-
- -); + {showJoinForm && ( +
+
+ +
+
+ )} + + ); +}; diff --git a/src/canvas/JoinPool/Preloader.tsx b/src/canvas/JoinPool/Preloader.tsx index c643d0a6a2..3326a3841a 100644 --- a/src/canvas/JoinPool/Preloader.tsx +++ b/src/canvas/JoinPool/Preloader.tsx @@ -14,8 +14,13 @@ import { capitalizeFirstLetter, planckToUnit, rmCommas } from '@w3ux/utils'; import { useNetwork } from 'contexts/Network'; import { useApi } from 'contexts/Api'; import { PoolSyncBar } from 'library/PoolSync/Bar'; +import type { PoolRewardPointsKey } from 'contexts/Pools/PoolPerformance/types'; -export const Preloader = () => { +export const Preloader = ({ + performanceKey, +}: { + performanceKey: PoolRewardPointsKey; +}) => { const { t } = useTranslation('pages'); const { network, @@ -51,7 +56,7 @@ export const Preloader = () => {
-

{t('pools.joinPool')}

+

{t('pools.pools')}

@@ -74,7 +79,7 @@ export const Preloader = () => {

- +

diff --git a/src/canvas/JoinPool/Wrappers.ts b/src/canvas/JoinPool/Wrappers.ts index 1447d35731..cc831bc612 100644 --- a/src/canvas/JoinPool/Wrappers.ts +++ b/src/canvas/JoinPool/Wrappers.ts @@ -28,21 +28,21 @@ export const JoinPoolInterfaceWrapper = styled.div` flex-grow: 1; display: flex; flex-direction: column; - padding-right: 4rem; @media (max-width: 1000px) { flex-basis: 100%; - padding-right: 0; } } &.side { - min-width: 450px; + min-width: 460px; + padding-left: 2.5rem; @media (max-width: 1000px) { flex-grow: 1; flex-basis: 100%; margin-top: 0.5rem; + padding-left: 0; } > div { diff --git a/src/canvas/JoinPool/index.tsx b/src/canvas/JoinPool/index.tsx index bad33992d5..6f08abadd1 100644 --- a/src/canvas/JoinPool/index.tsx +++ b/src/canvas/JoinPool/index.tsx @@ -24,12 +24,21 @@ export const JoinPool = () => { const { poolsMetaData, bondedPools } = useBondedPools(); const { getPoolRewardPoints, getPoolPerformanceTask } = usePoolPerformance(); + // Get the provided pool id and performance batch key from options, if available. + const providedPool = options?.providedPool; + const providedPoolId = providedPool?.id || null; + const performanceKey = + providedPoolId && providedPool?.performanceBatchKey + ? providedPool?.performanceBatchKey + : 'pool_join'; + // Get the pool performance task to determine if performance data is ready. - const poolJoinPerformanceTask = getPoolPerformanceTask('pool_join'); + const poolJoinPerformanceTask = getPoolPerformanceTask(performanceKey); + const performanceDataReady = poolJoinPerformanceTask.status === 'synced'; // Get performance data: Assumed to be fetched now. - const poolRewardPoints = getPoolRewardPoints('pool_join'); + const poolRewardPoints = getPoolRewardPoints(performanceKey); // The active canvas tab. const [activeTab, setActiveTab] = useState(0); @@ -64,7 +73,7 @@ export const JoinPool = () => { const initialSelectedPoolId = useMemo( () => - options?.poolId || + providedPoolId || filteredBondedPools[(filteredBondedPools.length * Math.random()) << 0] ?.id || 0, @@ -96,7 +105,7 @@ export const JoinPool = () => { return ( {poolJoinPerformanceTask.status !== 'synced' || !bondedPool ? ( - + ) : ( <>
{ setSelectedPoolId={setSelectedPoolId} bondedPool={bondedPool} metadata={poolsMetaData[selectedPoolId]} - autoSelected={options?.poolId === undefined} + autoSelected={providedPoolId === undefined} filteredBondedPools={filteredBondedPools} + providedPoolId={providedPoolId} />
- {activeTab === 0 && } + {activeTab === 0 && ( + + )} {activeTab === 1 && ( void; setSelectedPoolId: Dispatch>; + providedPoolId: number; } export interface NominationsProps { @@ -27,4 +29,5 @@ export interface AddressSectionProps { export interface OverviewSectionProps { bondedPool: BondedPool; + performanceKey: PoolRewardPointsKey; } diff --git a/src/library/ListItem/Labels/JoinPool.tsx b/src/library/ListItem/Labels/JoinPool.tsx index b6e98cb25b..b15d8d503c 100644 --- a/src/library/ListItem/Labels/JoinPool.tsx +++ b/src/library/ListItem/Labels/JoinPool.tsx @@ -9,11 +9,13 @@ import { useOverlay } from 'kits/Overlay/Provider'; export const JoinPool = ({ id, setActiveTab, + disabled, }: { id: number; setActiveTab: (t: number) => void; + disabled: boolean; }) => { - const { t } = useTranslation('library'); + const { t } = useTranslation('tips'); const { openCanvas } = useOverlay().canvas; return ( @@ -24,14 +26,18 @@ export const JoinPool = ({ openCanvas({ key: 'JoinPool', options: { - poolId: id, + providedPool: { + id, + performanceBatchKey: 'pool_page', + }, onJoinCallback: () => setActiveTab(0), }, size: 'xl', }); }} + disabled={disabled} > - {t('join')} + {t('module.more')}
diff --git a/src/library/ListItem/Wrappers.ts b/src/library/ListItem/Wrappers.ts index bf449628cf..f56c3f20a3 100644 --- a/src/library/ListItem/Wrappers.ts +++ b/src/library/ListItem/Wrappers.ts @@ -12,7 +12,7 @@ export const Wrapper = styled.div` &.member { --height-bottom-row: 2.75rem; } - &.pool-join { + &.pool-more { --height-bottom-row: 7.5rem; } @@ -155,6 +155,12 @@ export const Labels = styled.div` &:hover { opacity: 1; } + + &:disabled { + &:hover { + opacity: var(--opacity-disabled); + } + } > svg { margin-left: 0.3rem; } diff --git a/src/library/Pool/index.tsx b/src/library/Pool/index.tsx index facef6ae8e..27ecee3663 100644 --- a/src/library/Pool/index.tsx +++ b/src/library/Pool/index.tsx @@ -1,15 +1,6 @@ // Copyright 2024 @paritytech/polkadot-staking-dashboard authors & contributors // SPDX-License-Identifier: GPL-3.0-only -import { faCopy } from '@fortawesome/free-regular-svg-icons'; -import { faBars, faProjectDiagram } from '@fortawesome/free-solid-svg-icons'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import type { MouseEvent as ReactMouseEvent } from 'react'; -import { useTranslation } from 'react-i18next'; -import { useMenu } from 'contexts/Menu'; -import type { NotificationText } from 'controllers/NotificationsController/types'; -import { useBondedPools } from 'contexts/Pools/BondedPools'; -import { useValidators } from 'contexts/Validators/ValidatorEntries'; import { usePoolCommission } from 'hooks/usePoolCommission'; import { FavoritePool } from 'library/ListItem/Labels/FavoritePool'; import { PoolBonded } from 'library/ListItem/Labels/PoolBonded'; @@ -17,130 +8,29 @@ import { PoolCommission } from 'library/ListItem/Labels/PoolCommission'; import { PoolIdentity } from 'library/ListItem/Labels/PoolIdentity'; import { Labels, Separator, Wrapper } from 'library/ListItem/Wrappers'; import { usePoolsTabs } from 'pages/Pools/Home/context'; -import { useOverlay } from 'kits/Overlay/Provider'; -import { useActiveAccounts } from 'contexts/ActiveAccounts'; -import { useImportedAccounts } from 'contexts/Connect/ImportedAccounts'; import { JoinPool } from '../ListItem/Labels/JoinPool'; import { Members } from '../ListItem/Labels/Members'; import { PoolId } from '../ListItem/Labels/PoolId'; import type { PoolProps } from './types'; import { Rewards } from './Rewards'; -import { NotificationsController } from 'controllers/NotificationsController'; -import type { MenuItem } from 'contexts/Menu/types'; -import { useBalances } from 'contexts/Balances'; import { useSyncing } from 'hooks/useSyncing'; -import { MenuList } from 'library/Menu/List'; export const Pool = ({ pool }: PoolProps) => { - const { t } = useTranslation('library'); - const { memberCounter, addresses, id, state } = pool; - const { openMenu, open } = useMenu(); - const { validators } = useValidators(); + const { memberCounter, addresses, id } = pool; const { setActiveTab } = usePoolsTabs(); - const { openModal } = useOverlay().modal; - const { getPoolMembership } = useBalances(); - const { poolsNominations } = useBondedPools(); - const { activeAccount } = useActiveAccounts(); const { syncing } = useSyncing(['active-pools']); - const { isReadOnlyAccount } = useImportedAccounts(); const { getCurrentCommission } = usePoolCommission(); - const membership = getPoolMembership(activeAccount); const currentCommission = getCurrentCommission(id); - // get metadata from pools metabatch - const nominations = poolsNominations[pool.id]; - - // get pool targets from nominations metadata - const targets = nominations?.targets || []; - - // extract validator entries from pool targets - const targetValidators = validators.filter(({ address }) => - targets.includes(address) - ); - - // copy address notification - const notificationCopyAddress = ( - key: 'stash' | 'reward' - ): NotificationText | null => - addresses[key] == null - ? null - : { - title: t('addressCopiedToClipboard'), - subtitle: addresses[key], - }; - - // Consruct pool menu items. - const menuItems: MenuItem[] = []; - - // Add view pool nominations button to menu - menuItems.push({ - icon: , - title: `${t('viewPoolNominations')}`, - cb: () => { - openModal({ - key: 'PoolNominations', - options: { - nominator: addresses.stash, - targets: targetValidators, - }, - }); - }, - }); - - // add copy pool stash address button to menu - menuItems.push({ - icon: , - title: t('copyPoolAddress', { type: 'Stash' }), - cb: () => { - const notification = notificationCopyAddress('stash'); - if (notification) { - navigator.clipboard.writeText(addresses.stash); - NotificationsController.emit(notification); - } - }, - }); - - // add copy pool reward address button to menu - menuItems.push({ - icon: , - title: t('copyPoolAddress', { type: 'Reward' }), - cb: () => { - const notification = notificationCopyAddress('reward'); - if (notification) { - navigator.clipboard.writeText(addresses.reward); - NotificationsController.emit(notification); - } - }, - }); - - // Handler for opening menu. - const toggleMenu = (ev: ReactMouseEvent) => { - if (!open) { - openMenu(ev, ); - } - }; - - const displayJoin = - !syncing && - state === 'Open' && - !membership && - !isReadOnlyAccount(activeAccount) && - activeAccount; - return ( - +
-
- -
@@ -158,11 +48,14 @@ export const Pool = ({ pool }: PoolProps) => { - {displayJoin && ( - - - - )} + + + +
diff --git a/src/library/PoolSync/Bar.tsx b/src/library/PoolSync/Bar.tsx index fd11802626..bd9788f948 100644 --- a/src/library/PoolSync/Bar.tsx +++ b/src/library/PoolSync/Bar.tsx @@ -3,12 +3,17 @@ import BigNumber from 'bignumber.js'; import { usePoolPerformance } from 'contexts/Pools/PoolPerformance'; +import type { PoolRewardPointsKey } from 'contexts/Pools/PoolPerformance/types'; -export const PoolSyncBar = () => { +export const PoolSyncBar = ({ + performanceKey, +}: { + performanceKey: PoolRewardPointsKey; +}) => { const { getPoolPerformanceTask } = usePoolPerformance(); // Get the pool performance task to determine if performance data is ready. - const poolJoinPerformanceTask = getPoolPerformanceTask('pool_join'); + const poolJoinPerformanceTask = getPoolPerformanceTask(performanceKey); // Calculate syncing status. const { startEra, currentEra, endEra } = poolJoinPerformanceTask; diff --git a/src/library/PoolSync/index.tsx b/src/library/PoolSync/index.tsx index 216cee80e5..e7fd7c0b23 100644 --- a/src/library/PoolSync/index.tsx +++ b/src/library/PoolSync/index.tsx @@ -3,12 +3,19 @@ import BigNumber from 'bignumber.js'; import { usePoolPerformance } from 'contexts/Pools/PoolPerformance'; +import type { PoolRewardPointsKey } from 'contexts/Pools/PoolPerformance/types'; -export const PoolSync = ({ label }: { label?: string }) => { +export const PoolSync = ({ + label, + performanceKey, +}: { + label?: string; + performanceKey: PoolRewardPointsKey; +}) => { const { getPoolPerformanceTask } = usePoolPerformance(); // Get the pool performance task to determine if performance data is ready. - const poolJoinPerformanceTask = getPoolPerformanceTask('pool_join'); + const poolJoinPerformanceTask = getPoolPerformanceTask(performanceKey); if (poolJoinPerformanceTask.status !== 'syncing') { return null; diff --git a/src/locale/cn/library.json b/src/locale/cn/library.json index 65e3b9ec4b..43bdfd1293 100644 --- a/src/locale/cn/library.json +++ b/src/locale/cn/library.json @@ -23,7 +23,7 @@ "allowCompound": "允许复利", "allowWithdraw": "允许取出收益", "alreadyImported": "地址已导入", - "analyzingPoolPerformance": "分析提名池性能并找到最佳提名池", + "analyzingPoolPerformance": "分析提名池性能", "asAPoolMember": "作为提名池成员", "asThePoolDepositor": "作为提名池存款人", "atLeast": "质押金最低为", diff --git a/src/locale/en/library.json b/src/locale/en/library.json index 43023d92c6..8c844b5239 100644 --- a/src/locale/en/library.json +++ b/src/locale/en/library.json @@ -23,7 +23,7 @@ "allowCompound": "Allow Compound", "allowWithdraw": "Allow Withdraw", "alreadyImported": "Address Already Imported", - "analyzingPoolPerformance": "Analyzing pool performance and finding optimal pools.", + "analyzingPoolPerformance": "Analyzing pool performance", "asAPoolMember": "as a pool member.", "asThePoolDepositor": "as the pool depositor.", "atLeast": "Bond amount must be at least", diff --git a/src/modals/PoolNominations/Wrappers.ts b/src/modals/PoolNominations/Wrappers.ts deleted file mode 100644 index 9348154c0a..0000000000 --- a/src/modals/PoolNominations/Wrappers.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2024 @paritytech/polkadot-staking-dashboard authors & contributors -// SPDX-License-Identifier: GPL-3.0-only - -import styled from 'styled-components'; - -export const ListWrapper = styled.div` - display: flex; - flex-flow: column wrap; - align-items: center; - position: relative; - width: 100%; - - > div, - h3 { - width: 100%; - } -`; diff --git a/src/modals/PoolNominations/index.tsx b/src/modals/PoolNominations/index.tsx deleted file mode 100644 index 6e6db3e987..0000000000 --- a/src/modals/PoolNominations/index.tsx +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2024 @paritytech/polkadot-staking-dashboard authors & contributors -// SPDX-License-Identifier: GPL-3.0-only - -import { useTranslation } from 'react-i18next'; -import { Title } from 'library/Modal/Title'; -import { ValidatorList } from 'library/ValidatorList'; -import { useOverlay } from 'kits/Overlay/Provider'; -import { ListWrapper } from './Wrappers'; -import { ModalPadding } from 'kits/Overlay/structure/ModalPadding'; - -export const PoolNominations = () => { - const { t } = useTranslation('modals'); - const { - config: { options }, - } = useOverlay().modal; - const { nominator, targets } = options; - - return ( - <> - - <ModalPadding> - <ListWrapper> - {targets.length > 0 ? ( - <ValidatorList - format="nomination" - bondFor="pool" - validators={targets} - nominator={nominator} - showMenu={false} - displayFor="modal" - allowListFormat={false} - refetchOnListUpdate - /> - ) : ( - <h3>{t('poolIsNotNominating')}</h3> - )} - </ListWrapper> - </ModalPadding> - </> - ); -}; diff --git a/src/overlay/index.tsx b/src/overlay/index.tsx index 5c7101bd9d..56960499cd 100644 --- a/src/overlay/index.tsx +++ b/src/overlay/index.tsx @@ -19,7 +19,6 @@ import { ImportVault } from '../modals/ImportVault'; import { ManageFastUnstake } from '../modals/ManageFastUnstake'; import { ManagePool } from '../modals/ManagePool'; import { Networks } from '../modals/Networks'; -import { PoolNominations } from '../modals/PoolNominations'; import { Settings } from '../modals/Settings'; import { Unbond } from '../modals/Unbond'; import { UnlockChunks } from '../modals/UnlockChunks'; @@ -58,7 +57,6 @@ export const Overlays = () => { ManagePool, ManageFastUnstake, Networks, - PoolNominations, Settings, ValidatorMetrics, ValidatorGeo, diff --git a/src/pages/Pools/Home/Status/NewMember.tsx b/src/pages/Pools/Home/Status/NewMember.tsx index acc41d3fd1..dbc15dfc71 100644 --- a/src/pages/Pools/Home/Status/NewMember.tsx +++ b/src/pages/Pools/Home/Status/NewMember.tsx @@ -78,7 +78,7 @@ export const NewMember = ({ syncing }: NewMemberProps) => { <FontAwesomeIcon icon={faUserPlus} /> </> )} - <PoolSync /> + <PoolSync performanceKey="pool_join" /> </button> </div> </div>