Skip to content

Commit

Permalink
feat: start integrating stake accounts
Browse files Browse the repository at this point in the history
  • Loading branch information
icfor committed Mar 26, 2024
1 parent 1be9d8c commit e69fb36
Show file tree
Hide file tree
Showing 13 changed files with 355 additions and 205 deletions.
1 change: 1 addition & 0 deletions public/locales/en/staking.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"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",
"stakeAccounts": "Accounts",
"staked by forbole": "Staked by Forbole",
"staking para 1": "The action that token holders stake their tokens to validators to secure the network is called staking. Staked tokens are eligible to receive staking rewards. Newly minted tokens and transactions fees are given out as rewards to bonded staking token holders.",
"staking para 2": "Stakers stake their staking power to validators, but that does not mean the validators possess or have custody of the tokens staked to them. In other words, validators cannot steal or take away stakers’ tokens. Your staked amount of tokens will not be decreased in most situations, however, if your validator is punished by slashing, your staked token is at risk of being slashed too (see below for “slashing”).",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh-CN/staking.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"stake desc": "作为通证持有人,你可以安心在我们的基础建设上委托质押原生通证",
"stake with us!": "与我们一起赌注!",
"stake_now": "立即质押",
"stakeAccounts": "Accounts",
"staked by forbole": "Forbole 质押",
"staking para 1": "代币持有者将其代币质押给验证者以保护网络的行为称为质押。",
"staking para 2": "质押者将质押权质押给验证者,但这并不意味着验证者拥有或保管质押给他们的代币。",
Expand Down
1 change: 1 addition & 0 deletions public/locales/zh-HK/staking.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
"stake desc": "作為通證持有人,你可以安心在我們的基礎建設上委託質押原生通證",
"stake with us!": "與我們一起賭注!",
"stake_now": "立即質押",
"stakeAccounts": "Accounts",
"staked by forbole": "Forbole 質押",
"staking para 1": "代幣持有者將其代幣質押給驗證者以保護網路的行為稱為質押。",
"staking para 2": "質押者將質押權質押給驗證者,但這並不意味著驗證者擁有或保管質押給他們的代幣。",
Expand Down
20 changes: 0 additions & 20 deletions src/components/icons/solana_wallet.svg

This file was deleted.

11 changes: 11 additions & 0 deletions src/components/icons/solflare.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -102,57 +102,6 @@ $popover-background: linear-gradient(
width: 100%;
}

.stakingData {
background: #ffffff8f;
border-radius: 8px;
box-shadow:
0 10px 32px -4px #0226e11a,
0 6px 14px -6px #0226e11f;
display: flex;
flex-direction: column;
gap: 12px;
line-break: anywhere;
margin-bottom: 8px;
max-width: 100%;
padding: 12px 16px;
width: 100%;

.unbonding,
.rewards,
.total {
align-items: center;
display: flex;
flex-direction: row;
font-size: 16px;
justify-content: space-between;
width: 100%;

> div {
font-size: 16px;
font-style: normal;
font-weight: 600;
letter-spacing: 0.032px;
line-height: 20px;
text-shadow: $box-shadow-variant-3;
}

> div:first-child {
color: #25282d;
text-align: left;
}

> div:last-child {
text-align: right;
}
}

.rewards {
> div:nth-child(2) {
color: #059c78;
}
}
}

.buttons {
display: flex;
flex-direction: column;
Expand All @@ -177,16 +126,3 @@ $popover-background: linear-gradient(
body .stake {
font-size: 16px;
}

.totalValue {
> div:nth-child(2) {
color: #616161;
font-size: 14px;
font-style: normal;
font-weight: 400;
letter-spacing: 0.308px;
line-height: 20px;
text-align: right;
text-shadow: $box-shadow-variant-3;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@ import type {
ReactNode,
SetStateAction,
} from "react";
import { useContext, useEffect, useMemo, useState } from "react";
import { useEffect, useMemo, useRef, useState } from "react";

import CtaButton from "@src/components/cta-button";
import EmptyButton from "@src/components/empty-button";
import HighlightButton from "@src/components/highlight-button";
import CloseIcon from "@src/components/icons/icon_cross.svg";
import IconInfoCircle from "@src/components/icons/info-circle.svg";
import { tooltipId } from "@src/components/tooltip";
import {
StakingContext,
useStakingRef,
} from "@src/screens/staking/lib/staking_sdk/context";
import { useStakingRef } from "@src/screens/staking/lib/staking_sdk/context";
import {
fetchCoinPriceForNetwork,
getNetworkStakingInfo,
Expand All @@ -27,12 +24,9 @@ import type { NetworkClaimableRewards } from "@src/screens/staking/lib/staking_s
import {
getAccountsForNetwork,
getClaimableRewardsForNetwork,
getCoinPriceForNetwork,
getHasNetworkSupportedWallet,
getNetworkTVL,
getNetworkVotingPower,
getStakedDataForNetwork,
getUnbondingTokensForNetwork,
} from "@src/screens/staking/lib/staking_sdk/context/selectors";
import {
networkKeyToNetworkId,
Expand All @@ -42,12 +36,8 @@ import type {
Account,
StakingNetworkInfo,
} 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,
formatStakedDataUSD,
} from "@src/screens/staking/lib/staking_sdk/formatters";
import { formatCoin } from "@src/screens/staking/lib/staking_sdk/formatters";
import {
accountHasDelegations,
accountHasRewards,
Expand All @@ -58,6 +48,7 @@ import type { Network, NetworkKey } from "@src/utils/network_info";

import type { ParamsProps } from "../../config";
import * as styles from "./popover.module.scss";
import StakingDataBox from "./staking_data_box";

type PopOverProps = {
canClickNetwork: boolean;
Expand All @@ -78,6 +69,7 @@ const PopOver = ({
}: PopOverProps) => {
const networkNetworkId = networkKeyToNetworkId[network.key as NetworkKey];
const stakingNetworkId = networkKeyToNetworkId[network.key as NetworkKey];
const nodeRef = useRef<HTMLDivElement | null>(null);

const stakingRef = useStakingRef();

Expand All @@ -95,10 +87,21 @@ const PopOver = ({
const [stakingNetworkInfo, setStakingNetworkInfo] =
useState<null | StakingNetworkInfo>(null);

const { state: stakingState } = useContext(StakingContext);

const { state: stakingState } = stakingRef.current;
const { hasInit } = stakingState;

useEffect(() => {
if (!nodeRef.current) return;

const box = nodeRef.current.getBoundingClientRect();

if (box.left < 0) {
(nodeRef.current as HTMLElement).style.left = "0";
} else if (box.right > window.innerWidth) {
(nodeRef.current as HTMLElement).style.right = "0";
}
}, [nodeRef]);

useEffect(() => {
if (stakingNetworkId) {
getNetworkStakingInfo(stakingRef.current, stakingNetworkId).then(
Expand All @@ -109,52 +112,30 @@ const PopOver = ({
}
}, [stakingNetworkId, stakingRef]);

const { accounts, claimableRewards, stakedData, unbondingTokens } =
useMemo(() => {
const wallet = WalletId.Keplr;

const result = {
accounts: null as Account[] | null,
claimableRewards: null as NetworkClaimableRewards | null,
stakedData: null as Coin | null,
unbondingTokens: null as { period: string; text: string } | null,
};

if (!!stakingNetworkId && !!wallet) {
result.accounts = getAccountsForNetwork(stakingState, stakingNetworkId);
const { accounts, claimableRewards } = useMemo(() => {
const wallet = WalletId.Keplr;

if (!result.accounts?.length) {
return result;
}
const result = {
accounts: null as Account[] | null,
claimableRewards: null as NetworkClaimableRewards | null,
};

result.stakedData = getStakedDataForNetwork(
stakingRef.current.state,
stakingNetworkId,
);
if (!!stakingNetworkId && !!wallet) {
result.accounts = getAccountsForNetwork(stakingState, stakingNetworkId);

result.claimableRewards =
getClaimableRewardsForNetwork(
stakingRef.current.state,
stakingNetworkId,
) || null;
if (!result.accounts?.length) {
return result;
}

const unbonding = getUnbondingTokensForNetwork(
result.claimableRewards =
getClaimableRewardsForNetwork(
stakingRef.current.state,
stakingNetworkId,
);

if (unbonding) {
result.unbondingTokens = {
period: unbonding.period
? new Date(Number(unbonding.period) * 1000).toLocaleString()
: "",
text: formatCoin(unbonding.coin, { decimals: 4 }),
};
}
}
) || null;
}

return result;
}, [stakingState, stakingNetworkId, stakingRef]);
return result;
}, [stakingState, stakingNetworkId, stakingRef]);

useEffect(() => {
fetchCoinPriceForNetwork(stakingRef.current, stakingNetworkId);
Expand All @@ -163,31 +144,13 @@ const PopOver = ({
const accountsWithDelegations = accounts?.filter(accountHasDelegations);
const accountsWithRewards = accounts?.filter(accountHasRewards);

const displayedRewards = claimableRewards
? `+${formatCoin(claimableRewards, { decimals: 4 })}`
: null;

const displayedStaked = (() => {
if (!stakedData || !stakingNetworkId) return null;

const coinPrice = getCoinPriceForNetwork(
stakingRef.current.state,
stakingNetworkId,
);

if (!coinPrice) return [formatCoin(stakedData)];

const stakedDataUSD = formatStakedDataUSD(stakedData, coinPrice);

return [formatCoin(stakedData), stakedDataUSD].filter(Boolean);
})();

return (
<div
className={styles.popover}
onMouseLeave={() => {
setShowPopover("");
}}
ref={nodeRef}
>
<CloseIcon
className={styles.closeBtn}
Expand All @@ -196,51 +159,7 @@ const PopOver = ({
/>
<div>{networkImage}</div>
{network.name && <div className={styles.name}>{network.name}</div>}
{!![stakedData, claimableRewards, unbondingTokens].filter(Boolean)
.length && (
<div className={styles.stakingData}>
{displayedStaked && (
<div className={styles.total}>
<div>{t("totalStaked")}</div>
<div className={styles.totalValue}>
{displayedStaked.map((item, itemIdx) => (
<div key={itemIdx}>{item}</div>
))}
</div>
</div>
)}
{!!claimableRewards && (
<div className={styles.rewards}>
<div>{t("claimableRewards")}</div>
<div
data-tooltip-content={formatCoin(claimableRewards, {
maximumFractionDigits: 12,
})}
data-tooltip-id={tooltipId}
>
{displayedRewards}
</div>
</div>
)}
{!!unbondingTokens && (
<div className={styles.unbonding}>
<div>{t("unbondingTokens")}</div>
<div
data-tooltip-content={
!!unbondingTokens.period
? t("popover.unbondingTooltip", {
period: unbondingTokens.period,
})
: ""
}
data-tooltip-id={tooltipId}
>
{unbondingTokens.text}
</div>
</div>
)}
</div>
)}
<StakingDataBox network={network} />
{!!networkSummary && (
<div className={styles.dataBox}>
{(() => {
Expand Down
Loading

0 comments on commit e69fb36

Please sign in to comment.