From 5d70cd7aef120d1b88c8046a61082ce1a25172dc Mon Sep 17 00:00:00 2001 From: Jack Burrus Date: Mon, 23 Sep 2024 17:07:38 -0600 Subject: [PATCH] Add default Yield Multiplier to PoolRow and OpenShortForm (#1511) * Adds yield multiplier to pool row * replace variably apy with multiplier * check for loading * Skeleton loading * adds commend for multiplier calc * switch to parseFixed * Move calc into separate function --- .../calculateMarketYieldMultiplier.ts | 28 +++++++++++++++++++ .../src/ui/base/components/PrimaryStat.tsx | 17 ++++++++--- .../shorts/OpenShortForm/OpenShortForm.tsx | 6 ++-- .../src/ui/markets/PoolRow/PoolRow.tsx | 19 +++++++++---- 4 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 apps/hyperdrive-trading/src/hyperdrive/calculateMarketYieldMultiplier.ts diff --git a/apps/hyperdrive-trading/src/hyperdrive/calculateMarketYieldMultiplier.ts b/apps/hyperdrive-trading/src/hyperdrive/calculateMarketYieldMultiplier.ts new file mode 100644 index 000000000..c08654942 --- /dev/null +++ b/apps/hyperdrive-trading/src/hyperdrive/calculateMarketYieldMultiplier.ts @@ -0,0 +1,28 @@ +import { parseFixed } from "@delvtech/fixed-point-wasm"; +/** + * Calculates the yield multiplier for a Hyperdrive market based on the long price. + * + * The yield multiplier represents how much the underlying yield is amplified for short positions. + * It is inversely proportional to the long price, increasing as the long price approaches 1. + * + * Yield Multiplier calculation: + * Yield Multiplier = 1 / (1 - longPrice) + * + * Examples: + * - If longPrice = 0.9: + * Yield Multiplier = 1 / (1 - 0.9) = 1 / 0.1 = 10x + * The short position amplifies the underlying yield by 10 times. + * + * - If longPrice = 0.96: + * Yield Multiplier = 1 / (1 - 0.96) = 1 / 0.04 = 25x + * The short position amplifies the underlying yield by 25 times. + * + * @param longPrice The current price of a long position, represented as a bigint. + * @returns The calculated yield multiplier as a string, formatted to 2 decimal places. + */ + +export function calculateMarketYieldMultiplier(longPrice: bigint): string { + return parseFixed(1) + .div(parseFixed(1).sub(longPrice)) + .format({ decimals: 2, rounding: "trunc" }); +} diff --git a/apps/hyperdrive-trading/src/ui/base/components/PrimaryStat.tsx b/apps/hyperdrive-trading/src/ui/base/components/PrimaryStat.tsx index d097fa1a9..62c59dc4e 100644 --- a/apps/hyperdrive-trading/src/ui/base/components/PrimaryStat.tsx +++ b/apps/hyperdrive-trading/src/ui/base/components/PrimaryStat.tsx @@ -1,6 +1,7 @@ import { InformationCircleIcon } from "@heroicons/react/24/outline"; import classNames from "classnames"; import { ReactNode } from "react"; +import Skeleton from "react-loading-skeleton"; export function PrimaryStat({ label, @@ -11,6 +12,7 @@ export function PrimaryStat({ tooltipPosition = "top", valueClassName, unitClassName, + valueLoading = false, }: { label: string; value: ReactNode; @@ -20,6 +22,7 @@ export function PrimaryStat({ tooltipPosition?: "top" | "bottom" | "left" | "right"; valueClassName?: string; unitClassName?: string; + valueLoading?: boolean; }): JSX.Element { return (
@@ -43,10 +46,16 @@ export function PrimaryStat({ )}
-
{value}
- {valueUnit ? ( -
{valueUnit}
- ) : null} + {valueLoading ? ( + + ) : ( + <> +
{value}
+ {valueUnit ? ( +
{valueUnit}
+ ) : null} + + )}
{subValue && (
{subValue}
diff --git a/apps/hyperdrive-trading/src/ui/hyperdrive/shorts/OpenShortForm/OpenShortForm.tsx b/apps/hyperdrive-trading/src/ui/hyperdrive/shorts/OpenShortForm/OpenShortForm.tsx index 53c0840db..451c1835d 100644 --- a/apps/hyperdrive-trading/src/ui/hyperdrive/shorts/OpenShortForm/OpenShortForm.tsx +++ b/apps/hyperdrive-trading/src/ui/hyperdrive/shorts/OpenShortForm/OpenShortForm.tsx @@ -11,6 +11,7 @@ import { MouseEvent, ReactElement, useState } from "react"; import { MAX_UINT256 } from "src/base/constants"; import { formatRate } from "src/base/formatRate"; import { isTestnetChain } from "src/chains/isTestnetChain"; +import { calculateMarketYieldMultiplier } from "src/hyperdrive/calculateMarketYieldMultiplier"; import { getIsValidTradeSize } from "src/hyperdrive/getIsValidTradeSize"; import { getHasEnoughAllowance } from "src/token/getHasEnoughAllowance"; import { getHasEnoughBalance } from "src/token/getHasEnoughBalance"; @@ -82,7 +83,7 @@ export function OpenShortForm({ tokenAddress: baseToken.address, decimals: baseToken.decimals, }); - const { longPrice } = useCurrentLongPrice({ + const { longPrice, longPriceStatus } = useCurrentLongPrice({ chainId: hyperdrive.chainId, hyperdriveAddress: hyperdrive.address, }); @@ -274,7 +275,7 @@ export function OpenShortForm({ ? fixed(amountOfBondsToShortAsBigInt, activeToken.decimals) .div(traderDeposit, activeToken.decimals) .format({ decimals: 2, rounding: "trunc" }) - : "0"; + : calculateMarketYieldMultiplier(longPrice ?? 0n); const maturesOnLabel = formatDate( Date.now() + Number(hyperdrive.poolConfig.positionDuration * 1000n), @@ -423,6 +424,7 @@ export function OpenShortForm({ valueUnit="x" unitClassName="text-h3" subValue={`Matures on ${maturesOnLabel}`} + valueLoading={longPriceStatus === "loading"} />
} /> + - + {`${calculateMarketYieldMultiplier(longPrice)}x`} ) : ( "-" @@ -267,7 +274,7 @@ function PoolStat({ } return ( -
+