diff --git a/public/icons/stake_account.svg b/public/icons/stake_account.svg new file mode 100644 index 00000000..7e0ab17d --- /dev/null +++ b/public/icons/stake_account.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/public/locales/en/staking.json b/public/locales/en/staking.json index 90379c1e..41851968 100644 --- a/public/locales/en/staking.json +++ b/public/locales/en/staking.json @@ -1,4 +1,5 @@ { + "accounts": "Accounts", "addressCopied": "Address copied", "apy": "Annual Percentage Yield", "benefits bullet 1": "Earn your staking rewards, it allows you to earn rewards for securing the network with your contribution", @@ -107,6 +108,13 @@ "stake desc": "As a token holder, you can utilize our infrastructure by staking your tokens with us", "stake with us!": "Stake with us!", "stake_now": "Stake Now", + "stakeAccount": { + "status": { + "activating": "Active", + "active": "Active", + "deactivating": "Deactivating" + } + }, "stakeAccounts": "Accounts", "staked by forbole": "Staked by Forbole", "staking": { diff --git a/public/locales/zh-CN/staking.json b/public/locales/zh-CN/staking.json index 5d7272b4..b9c3144c 100644 --- a/public/locales/zh-CN/staking.json +++ b/public/locales/zh-CN/staking.json @@ -1,4 +1,5 @@ { + "accounts": "Accounts", "addressCopied": "地址已复制", "apy": "年收益率", "benefits bullet 1": "赚取您的质押奖励,它可以让您通过贡献来获得保护网络的奖励", @@ -106,6 +107,13 @@ "stake desc": "作为通证持有人,你可以安心在我们的基础建设上委托质押原生通证", "stake with us!": "与我们一起赌注!", "stake_now": "立即质押", + "stakeAccount": { + "status": { + "activating": "Active", + "active": "Active", + "deactivating": "Deactivating" + } + }, "stakeAccounts": "Accounts", "staked by forbole": "Forbole 质押", "staking": { diff --git a/public/locales/zh-HK/staking.json b/public/locales/zh-HK/staking.json index c1c5b580..57469a0d 100644 --- a/public/locales/zh-HK/staking.json +++ b/public/locales/zh-HK/staking.json @@ -1,4 +1,5 @@ { + "accounts": "Accounts", "addressCopied": "地址已複製", "apy": "年報酬率", "benefits bullet 1": "賺取您的質押獎勵,它可以讓您透過貢獻來獲得保護網路的獎勵", @@ -106,6 +107,13 @@ "stake desc": "作為通證持有人,你可以安心在我們的基礎建設上委託質押原生通證", "stake with us!": "與我們一起賭注!", "stake_now": "立即質押", + "stakeAccount": { + "status": { + "activating": "Active", + "active": "Active", + "deactivating": "Deactivating" + } + }, "stakeAccounts": "Accounts", "staked by forbole": "Forbole 質押", "staking": { diff --git a/src/screens/staking/components/networks/components/network_grid/components/network_card/popover.tsx b/src/screens/staking/components/networks/components/network_grid/components/network_card/popover.tsx index e592d2fb..29087782 100644 --- a/src/screens/staking/components/networks/components/network_grid/components/network_card/popover.tsx +++ b/src/screens/staking/components/networks/components/network_grid/components/network_card/popover.tsx @@ -141,6 +141,9 @@ const PopOver = ({ fetchCoinPriceForNetwork(stakingRef.current, stakingNetworkId); }, [stakingRef, stakingNetworkId]); + // @TODO: Remove + const [, rerender] = useState(0); + const accountsWithDelegations = accounts?.filter(accountHasDelegations); const accountsWithRewards = accounts?.filter(accountHasRewards); @@ -158,6 +161,13 @@ const PopOver = ({ onClickCapture={() => setShowPopover("")} />
{networkImage}
+ {network.name &&
{network.name}
} {!!networkSummary && ( diff --git a/src/screens/staking/components/networks/components/network_grid/components/network_card/stake_accounts.module.scss b/src/screens/staking/components/networks/components/network_grid/components/network_card/stake_accounts.module.scss new file mode 100644 index 00000000..04997b11 --- /dev/null +++ b/src/screens/staking/components/networks/components/network_grid/components/network_card/stake_accounts.module.scss @@ -0,0 +1,111 @@ +@import "src/styles/sass.scss"; + +.statusActivating { + background: #007fff; +} + +.statusActive { + background: #1ec490; +} + +.statusDeactivating { + background: #e4a11e; +} + +.statusActivating, +.statusActive, +.statusDeactivating { + align-items: flex-start; + border-radius: 4px; + color: #fff; + display: inline-block; + font-size: 12px; + gap: 10px; + padding: 2px 4px; +} + +.stakeAccount { + align-items: center; + background: rgba(255, 255, 255, 0.34); + box-shadow: + 0 6px 14px -6px rgba(2, 38, 225, 0.12), + 0 10px 32px -4px rgba(2, 38, 225, 0.1); + display: flex; + flex-direction: row; + justify-content: space-between; + padding: 12px; + width: 100%; +} + +.external { + img { + height: 20px; + width: 20px; + } +} + +.stakeIcon { + height: 20px; + width: 20px; +} + +.title { + align-items: center; + display: flex; + flex-direction: row; + gap: 4px; + justify-content: flex-start; + + span { + color: #25282d; + font-size: 12px; + font-weight: 600; + line-height: 16px; + text-shadow: + 0 8px 22px rgba(2, 38, 225, 0.12), + 0 14px 64px rgba(2, 38, 225, 0.12); + } +} + +.left { + display: flex; + flex-direction: column; + gap: 4px; +} + +.status { + display: flex; + justify-content: flex-start; +} + +.value { + color: #25282d; + font-size: 16px; + font-weight: 600; + letter-spacing: 0.032px; + line-height: 20px; + text-align: right; + text-shadow: + 0 8px 22px rgba(2, 38, 225, 0.12), + 0 14px 64px rgba(2, 38, 225, 0.12); +} + +.numbers { + align-items: flex-end; + display: flex; + flex-direction: column; + gap: 4px; + justify-content: space-between; +} + +.extra { + color: #059c78; + font-size: 14px; + font-weight: 400; + letter-spacing: 0.308px; + line-height: 20px; + text-align: right; + text-shadow: + 0 8px 22px rgba(2, 38, 225, 0.12), + 0 14px 64px rgba(2, 38, 225, 0.12); +} diff --git a/src/screens/staking/components/networks/components/network_grid/components/network_card/stake_accounts.tsx b/src/screens/staking/components/networks/components/network_grid/components/network_card/stake_accounts.tsx new file mode 100644 index 00000000..53aadccc --- /dev/null +++ b/src/screens/staking/components/networks/components/network_grid/components/network_card/stake_accounts.tsx @@ -0,0 +1,154 @@ +import useTranslation from "next-translate/useTranslation"; +import { useEffect, useMemo } from "react"; + +import { useStakingRef } from "@src/screens/staking/lib/staking_sdk/context"; +import { fetchCoinPriceForNetwork } from "@src/screens/staking/lib/staking_sdk/context/actions"; +import type { NetworkClaimableRewards } from "@src/screens/staking/lib/staking_sdk/context/selectors"; +import { + getClaimableRewardsForNetwork, + getStakeAccountsForNetwork, + getStakedDataForNetwork, + getUnbondingTokensForNetwork, +} from "@src/screens/staking/lib/staking_sdk/context/selectors"; +import { networkKeyToNetworkId } from "@src/screens/staking/lib/staking_sdk/core"; +import type { Coin } from "@src/screens/staking/lib/staking_sdk/core/base"; +import { WalletId } from "@src/screens/staking/lib/staking_sdk/core/base"; +import { formatCoin } from "@src/screens/staking/lib/staking_sdk/formatters"; +import type { StakeAccount } from "@src/screens/staking/lib/staking_sdk/staking_client_types"; +import { getExplorerLink } from "@src/screens/staking/lib/staking_sdk/utils/accounts"; +import type { Network, NetworkKey } from "@src/utils/network_info"; + +import * as styles from "./stake_accounts.module.scss"; + +type Props = { + network: Network; + onClose: () => void; +}; + +const StakeAccounts = ({ network, onClose }: Props) => { + const stakingNetworkId = networkKeyToNetworkId[network.key as NetworkKey]; + + const stakingRef = useStakingRef(); + + const { t } = useTranslation("staking"); + + const { stakeAccounts } = useMemo(() => { + const wallet = WalletId.Keplr; + + const result = { + claimableRewards: null as NetworkClaimableRewards | null, + stakeAccounts: null as null | StakeAccount[], + stakedData: null as Coin | null, + unbondingTokens: null as { period: string; text: string } | null, + }; + + if (!!stakingNetworkId && !!wallet) { + result.stakeAccounts = getStakeAccountsForNetwork( + stakingRef.current.state, + stakingNetworkId, + ); + + result.stakedData = getStakedDataForNetwork( + stakingRef.current.state, + stakingNetworkId, + ); + + result.claimableRewards = + getClaimableRewardsForNetwork( + stakingRef.current.state, + stakingNetworkId, + ) || null; + + const unbonding = getUnbondingTokensForNetwork( + stakingRef.current.state, + stakingNetworkId, + ); + + if (unbonding) { + result.unbondingTokens = { + period: unbonding.period + ? new Date(Number(unbonding.period) * 1000).toLocaleString() + : "", + text: formatCoin(unbonding.coin, { decimals: 4 }), + }; + } + } + + return result; + }, [stakingNetworkId, stakingRef]); + + useEffect(() => { + fetchCoinPriceForNetwork(stakingRef.current, stakingNetworkId); + }, [stakingRef, stakingNetworkId]); + + return ( +
+
+ {t("accounts")}{" "} + {stakeAccounts?.length} +
+
+ {stakeAccounts?.map((account) => { + const shortenedAddress = `${account.address.slice(0, 8)}...`; + + const explorerLink = getExplorerLink( + account.address, + stakingNetworkId, + ); + + const statusLabel = + { + activating: t("stakeAccount.status.activating"), + active: t("stakeAccount.status.active"), + deactivating: t("stakeAccount.status.deactivating"), + }[account.status] || account.status; + + const statusStyle = + { + activating: styles.statusActivating, + active: styles.statusActive, + deactivating: styles.statusDeactivating, + }[account.status] || null; + + return ( +
+
+
+ + {shortenedAddress} + {!!explorerLink && ( + <> + {" "} + + + + + )} +
+
+ {!!statusStyle && ( + {statusLabel} + )} +
+
+
+
{formatCoin(account)}
+
+123
+
+
+ ); + })} +
+
+ ); +}; + +export default StakeAccounts; diff --git a/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.module.scss b/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.module.scss index def272e4..fe2f1405 100644 --- a/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.module.scss +++ b/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.module.scss @@ -63,16 +63,3 @@ text-shadow: $box-shadow-variant-3; } } - -.stakeAccount { - align-items: center; - display: flex; - flex-direction: row; - justify-content: space-between; - width: 100%; -} - -.external { - height: 20px; - width: 20px; -} diff --git a/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.tsx b/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.tsx index 40b989c4..26b869cc 100644 --- a/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.tsx +++ b/src/screens/staking/components/networks/components/network_grid/components/network_card/staking_data_box.tsx @@ -20,9 +20,9 @@ import { formatStakedDataUSD, } from "@src/screens/staking/lib/staking_sdk/formatters"; import type { StakeAccount } from "@src/screens/staking/lib/staking_sdk/staking_client_types"; -import { getExplorerLink } from "@src/screens/staking/lib/staking_sdk/utils/accounts"; import type { Network, NetworkKey } from "@src/utils/network_info"; +import StakeAccounts from "./stake_accounts"; import * as styles from "./staking_data_box.module.scss"; type PopOverProps = { @@ -122,52 +122,10 @@ const StakingDataBox = ({ network }: PopOverProps) => { const content = (() => { if (isDisplayingStakeAccounts) { return ( -
-
- {" "} - Accounts {stakeAccounts?.length} -
-
- {stakeAccounts?.map((account) => { - const shortenedAddress = `${account.address.slice(0, 8)}...`; - - const explorerLink = getExplorerLink( - account.address, - stakingNetworkId, - ); - - return ( -
-
-
- {shortenedAddress} - {!!explorerLink && ( - <> - {" "} - - - - - )} -
-
{account.status}
-
-
{formatCoin(account)}
-
- ); - })} -
-
+ setIsDisplayingStakeAccounts(false)} + /> ); }