-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
22 changed files
with
365 additions
and
258 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import { memo } from "react"; | ||
|
||
import { useAppState, type AppState } from "@/app/state"; | ||
import { getNetworkConfig } from "@/config/network.config"; | ||
import { satoshiToBtc } from "@/utils/btcConversions"; | ||
import { maxDecimals } from "@/utils/maxDecimals"; | ||
|
||
import { StatItem } from "./StatItem"; | ||
import { stakingTvlCap } from "./icons"; | ||
|
||
const { coinName } = getNetworkConfig(); | ||
|
||
type StakingCapAdapter = { | ||
match: (state: AppState) => boolean; | ||
adopt: (state: AppState) => JSX.Element | undefined; | ||
}; | ||
|
||
const STAKING_CAP_ITEMS: StakingCapAdapter[] = [ | ||
{ | ||
match: ({ isLoading, currentHeight, currentVersion }) => | ||
!currentHeight || !currentVersion || isLoading, | ||
adopt: ({ isLoading }) => ( | ||
<StatItem | ||
loading={isLoading} | ||
icon={stakingTvlCap} | ||
title="Staking TVL Cap" | ||
value="-" | ||
/> | ||
), | ||
}, | ||
|
||
{ | ||
match: ({ isApprochingNextVersion, nextVersion }) => | ||
isApprochingNextVersion && Boolean(nextVersion?.activationHeight), | ||
adopt: ({ | ||
nextVersion: { activationHeight = 0 } = {}, | ||
currentHeight = 0, | ||
}) => { | ||
const remainingBlocks = activationHeight - currentHeight - 1; | ||
|
||
return ( | ||
<StatItem | ||
icon={stakingTvlCap} | ||
title="Staking Window" | ||
value={`opens in ${remainingBlocks} ${remainingBlocks == 1 ? "block" : "blocks"}`} | ||
/> | ||
); | ||
}, | ||
}, | ||
|
||
{ | ||
match: ({ isApprochingNextVersion, nextVersion }) => | ||
isApprochingNextVersion && Boolean(nextVersion?.stakingCapSat), | ||
adopt: ({ nextVersion: { stakingCapSat = 0 } = {} }) => ( | ||
<StatItem | ||
icon={stakingTvlCap} | ||
title="Next Staking TVL Cap" | ||
value={`${maxDecimals(satoshiToBtc(stakingCapSat), 8)} ${coinName}`} | ||
/> | ||
), | ||
}, | ||
|
||
{ | ||
match: ({ currentVersion }) => Boolean(currentVersion?.stakingCapHeight), | ||
adopt: ({ | ||
currentVersion: { stakingCapHeight = 0 } = {}, | ||
currentHeight = 0, | ||
}) => { | ||
const numOfBlockLeft = stakingCapHeight - currentHeight; | ||
|
||
return ( | ||
<StatItem | ||
icon={stakingTvlCap} | ||
title="Staking Window" | ||
value={ | ||
numOfBlockLeft > 0 | ||
? `closes in ${numOfBlockLeft} ${numOfBlockLeft == 1 ? "block" : "blocks"}` | ||
: "closed" | ||
} | ||
/> | ||
); | ||
}, | ||
}, | ||
|
||
{ | ||
match: ({ currentVersion }) => Boolean(currentVersion?.stakingCapSat), | ||
adopt: ({ currentVersion: { stakingCapSat = 0 } = {} }) => ( | ||
<StatItem | ||
icon={stakingTvlCap} | ||
title="Staking TVL Cap" | ||
value={`${maxDecimals(satoshiToBtc(stakingCapSat), 8)} ${coinName}`} | ||
/> | ||
), | ||
}, | ||
|
||
{ | ||
match: () => true, | ||
adopt: () => ( | ||
<StatItem icon={stakingTvlCap} title="Staking TVL Cap" value="-" /> | ||
), | ||
}, | ||
]; | ||
|
||
export const StakingCapItem = memo(() => { | ||
const appState = useAppState(); | ||
const stakingCapAdapter = STAKING_CAP_ITEMS.find(({ match }) => | ||
match(appState), | ||
); | ||
|
||
return stakingCapAdapter?.adopt(appState); | ||
}); | ||
|
||
StakingCapItem.displayName = "StakingCapItem"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { type JSX } from "react"; | ||
import { AiOutlineInfoCircle } from "react-icons/ai"; | ||
import { Tooltip } from "react-tooltip"; | ||
|
||
interface StatItemProps { | ||
loading?: boolean; | ||
icon: JSX.Element; | ||
title: string; | ||
value: string | number; | ||
tooltip?: string; | ||
} | ||
|
||
export const StatItem = ({ | ||
loading, | ||
icon, | ||
title, | ||
value, | ||
tooltip, | ||
}: StatItemProps) => ( | ||
<div className="flex items-center gap-2 md:flex-1 md:flex-col lg:flex-initial lg:flex-row flex-wrap justify-center"> | ||
<div className="flex items-center gap-2"> | ||
{icon} | ||
<div className="flex items-center gap-1"> | ||
<p className="dark:text-neutral-content">{title}</p> | ||
{tooltip && ( | ||
<> | ||
<span | ||
className="cursor-pointer text-xs" | ||
data-tooltip-id={`tooltip-${title}`} | ||
data-tooltip-content={tooltip} | ||
data-tooltip-place="top" | ||
> | ||
<AiOutlineInfoCircle /> | ||
</span> | ||
<Tooltip id={`tooltip-${title}`} className="tooltip-wrap" /> | ||
</> | ||
)} | ||
</div> | ||
</div> | ||
|
||
<div> | ||
<p className="flex-1 text-right"> | ||
{loading ? ( | ||
<span className="loading loading-spinner text-primary" /> | ||
) : ( | ||
<strong>{value}</strong> | ||
)} | ||
</p> | ||
</div> | ||
</div> | ||
); |
Oops, something went wrong.