Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ import { useMaxShort } from "src/ui/hyperdrive/shorts/hooks/useMaxShort";
import { useOpenShort } from "src/ui/hyperdrive/shorts/hooks/useOpenShort";
import { usePreviewOpenShort } from "src/ui/hyperdrive/shorts/hooks/usePreviewOpenShort";
import { PositionPicker } from "src/ui/markets/PositionPicker";
import { useMorphoVaultRewards } from "src/ui/rewards/useMorphoRate";
import { eligibleMarketsForMorphoVaultRewards } from "src/ui/rewards/useRewards";
import { ApproveTokenChoices } from "src/ui/token/ApproveTokenChoices";
import { SlippageSettingsTwo } from "src/ui/token/SlippageSettingsTwo";
import { TokenInputTwo } from "src/ui/token/TokenInputTwo";
Expand All @@ -44,6 +46,7 @@ import { useTokenBalance } from "src/ui/token/hooks/useTokenBalance";
import { useTokenFiatPrice } from "src/ui/token/hooks/useTokenFiatPrice";
import { useYieldSourceRate } from "src/ui/vaults/useYieldSourceRate";
import { formatUnits } from "viem";
import { base } from "viem/chains";
import { useAccount, useChainId } from "wagmi";

(window as any).fixed = fixed;
Expand Down Expand Up @@ -237,6 +240,14 @@ export function OpenShortForm({
percentage: slippageAsBigInt,
});

const { morphoVaultReward } = useMorphoVaultRewards({
hyperdrive,
enabled:
eligibleMarketsForMorphoVaultRewards[base.id]?.includes(
hyperdrive.address
) ?? false,
});

const { openShort, openShortStatus } = useOpenShort({
chainId: hyperdrive.chainId,
hyperdriveAddress: hyperdrive.address,
Expand Down Expand Up @@ -266,7 +277,7 @@ export function OpenShortForm({
activeTokenBalance.value > maxBondsOut
? maxBondsOut
: activeTokenBalance?.value,
activeToken.decimals,
activeToken.decimals
);
}

Expand All @@ -281,7 +292,7 @@ export function OpenShortForm({
});

const maturesOnLabel = formatDate(
Date.now() + Number(hyperdrive.poolConfig.positionDuration * 1000n),
Date.now() + Number(hyperdrive.poolConfig.positionDuration * 1000n)
);
return (
<TransactionView
Expand Down Expand Up @@ -312,8 +323,8 @@ export function OpenShortForm({
activeInput === "bonds"
? amountOfBondsToShort || ""
: maxBondsOutFromPayment
? formatUnits(maxBondsOutFromPayment, baseToken.decimals)
: ""
? formatUnits(maxBondsOutFromPayment, baseToken.decimals)
: ""
}
settings={
<div className="mb-3 flex w-full items-center justify-between">
Expand All @@ -335,7 +346,18 @@ export function OpenShortForm({
vaultRateStatus === "success" && vaultRate ? (
<>
{appConfig.yieldSources[hyperdrive.yieldSource].shortName} @{" "}
{isNewPool ? "✨New✨" : `${vaultRate.formatted} APY`}
{isNewPool
? "✨New✨"
: `${
morphoVaultReward
? `${formatRate(
vaultRate.vaultRate +
BigInt(morphoVaultReward.supplyApr * 1e18),
18,
false
)}%`
: vaultRate.formatted
} APY`}
</>
) : null
}
Expand All @@ -348,7 +370,7 @@ export function OpenShortForm({
baseTokenPrice && traderDeposit
? fixed(
amountOfBondsToShortAsBigInt || 0n,
baseToken.decimals,
baseToken.decimals
).mul(baseTokenPrice).bigint
: 0n,
decimals: baseToken.decimals,
Expand Down Expand Up @@ -392,7 +414,7 @@ export function OpenShortForm({
balance:
activeTokenPrice && traderDeposit
? fixed(traderDeposit, activeToken.decimals).mul(
activeTokenPrice,
activeTokenPrice
).bigint
: 0n,
decimals: activeToken.decimals,
Expand Down Expand Up @@ -421,7 +443,9 @@ export function OpenShortForm({
<div className="flex justify-between px-4 py-8">
<PrimaryStat
label="Exposure Multiplier"
tooltipContent={`This represents how much exposure you get to ${appConfig.yieldSources[hyperdrive.yieldSource].shortName} compared to what you pay to open the short.`}
tooltipContent={`This represents how much exposure you get to ${
appConfig.yieldSources[hyperdrive.yieldSource].shortName
} compared to what you pay to open the short.`}
value={
<span className="text-h3 font-bold">{exposureMultiplier}</span>
}
Expand Down Expand Up @@ -520,7 +544,7 @@ export function OpenShortForm({
amountAsBigInt={paddedTraderDepositForAllowance}
amount={formatUnits(
paddedTraderDepositForAllowance || 0n,
activeToken.decimals,
activeToken.decimals
)}
/>
);
Expand Down
34 changes: 30 additions & 4 deletions apps/hyperdrive-trading/src/ui/markets/PoolRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import { AssetStack } from "src/ui/markets/AssetStack";
import { formatTermLength2 } from "src/ui/markets/formatTermLength";
import { MARKET_DETAILS_ROUTE } from "src/ui/markets/routes";
import { RewardsTooltip } from "src/ui/rewards/RewardsTooltip";
import { useMorphoVaultRewards } from "src/ui/rewards/useMorphoRate";
import { eligibleMarketsForMorphoVaultRewards } from "src/ui/rewards/useRewards";
import { base } from "viem/chains";
export interface PoolRowProps {
hyperdrive: HyperdriveConfig;
tvl: bigint;
Expand Down Expand Up @@ -55,6 +58,14 @@ export function PoolRow({
hyperdriveAddress: hyperdrive.address,
});

const { morphoVaultReward } = useMorphoVaultRewards({
hyperdrive,
enabled:
eligibleMarketsForMorphoVaultRewards[base.id]?.includes(
hyperdrive.address
) ?? false,
});

return (
<Well
as="div"
Expand Down Expand Up @@ -91,7 +102,7 @@ export function PoolRow({
<ClockIcon className="size-4 text-gray-400/60" />{" "}
<span className="text-neutral-content">
{formatTermLength2(
Number(hyperdrive.poolConfig.positionDuration * 1000n),
Number(hyperdrive.poolConfig.positionDuration * 1000n)
)}
</span>
</div>
Expand Down Expand Up @@ -185,7 +196,10 @@ export function PoolRow({
hyperdriveAddress={hyperdrive.address}
chainId={hyperdrive.chainId}
>
{`${calculateMarketYieldMultiplier(longPrice).format({ decimals: 2, rounding: "trunc" })}x`}
{`${calculateMarketYieldMultiplier(longPrice).format({
decimals: 2,
rounding: "trunc",
})}x`}
</RewardsTooltip>
) : (
"-"
Expand Down Expand Up @@ -217,7 +231,19 @@ export function PoolRow({
chainId={hyperdrive.chainId}
hyperdriveAddress={hyperdrive.address}
>
<PercentLabel value={formatRate(lpApy.lpApy, 18, false)} />
{morphoVaultReward ? (
<PercentLabel
// If this is a eligible for morpho vault rewards we need to add this to the existing lpApy. The supply APR is returned as a floating point number from the Morpho API so we need to scale it up to 18 decimals before adding it to the lpApy.
value={formatRate(
lpApy.lpApy +
BigInt(morphoVaultReward.supplyApr * 1e18),
18,
false
)}
/>
) : (
<PercentLabel value={formatRate(lpApy.lpApy, 18, false)} />
)}
</RewardsTooltip>
) : (
"-"
Expand Down Expand Up @@ -299,7 +325,7 @@ function PercentLabel({ value }: { value: string }) {
<div
className={classNames(
"font-dmMono text-h4 font-medium",
"after:text-h5 after:content-['%']",
"after:text-h5 after:content-['%']"
)}
>
{value}
Expand Down
72 changes: 56 additions & 16 deletions apps/hyperdrive-trading/src/ui/rewards/RewardsTooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,12 @@ import {
appConfig,
findHyperdriveConfig,
} from "@delvtech/hyperdrive-appconfig";
import { ChartBarIcon, SparklesIcon } from "@heroicons/react/16/solid";
import * as Tooltip from "@radix-ui/react-tooltip";
import { PropsWithChildren, ReactNode } from "react";
import { assertNever } from "src/base/assertNever";
import { formatRate } from "src/base/formatRate";
import { useLpApy } from "src/ui/hyperdrive/hooks/useLpApy";
import { useRewards } from "src/ui/rewards/useRewards";
import { Address } from "viem";

Expand All @@ -24,6 +27,8 @@ export function RewardsTooltip({

const rewards = useRewards(hyperdrive);

const { lpApy } = useLpApy({ chainId, hyperdriveAddress });

if (!rewards || (rewards && rewards.length === 0)) {
return children;
}
Expand Down Expand Up @@ -74,25 +79,60 @@ export function RewardsTooltip({

case "MorphoVault":
return (
<div
key={reward.id}
className="flex items-center justify-between border-b border-neutral-content/30 p-3 [&:nth-last-child(2)]:border-none"
>
<div className="flex items-center gap-1">
<img
src={reward.iconUrl}
alt={`${reward.name} logo`}
className="h-4"
/>
{reward.name}
<>
<div
key={reward.id}
className="flex items-center justify-between border-b border-neutral-content/30 p-3 [&:nth-last-child(2)]:border-none"
>
<div className="flex items-center gap-1">
<img
src={reward.iconUrl}
alt={`${reward.name} logo`}
className="h-4"
/>
{reward.name}
</div>

<div className="grid justify-items-end">
<p className="flex items-center gap-1">
+{reward.amount}
</p>
</div>
</div>
<div className="flex items-center justify-between border-b border-neutral-content/30 p-3 [&:nth-last-child(2)]:border-none">
<div className="flex items-center gap-1">
<ChartBarIcon className="h-4" />
Rate
</div>

<div className="grid justify-items-end">
<p className="flex items-center gap-1">
+{reward.amount}
</p>
<div className="grid justify-items-end">
<p className="flex items-center gap-1">
+{formatRate(BigInt(lpApy?.lpApy || 0), 18, false)}%
</p>
</div>
</div>
</div>
<div className="flex items-center justify-between border-b border-neutral-content/30 p-3 [&:nth-last-child(2)]:border-none">
<div className="flex items-center gap-1">
<SparklesIcon className="h-4" />
Net APY
</div>

<div className="grid justify-items-end">
<p className="flex items-center gap-1">
+
{formatRate(
(lpApy?.lpApy || 0n) +
BigInt(
(parseFloat(reward.amount) * 10 ** 18) / 100
),
18,
false
)}
%
</p>
</div>
</div>
</>
);
case "LineaLXPL":
return (
Expand Down
29 changes: 14 additions & 15 deletions apps/hyperdrive-trading/src/ui/rewards/useRewards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ const eligibleMarketsForMorphoRewards: Record<number, Address[]> = {
],
};

const eligibleMarketsForMorphoVaultRewards: Record<number, Address[]> = {
export const eligibleMarketsForMorphoVaultRewards: Record<number, Address[]> = {
[base.id]: [
// 182d Moonwell Flagship ETH
"0xceD9F810098f8329472AEFbaa1112534E96A5c7b",
Expand Down Expand Up @@ -88,6 +88,19 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined {
};
rewards.push(morphoReward);
}
if (
eligibleMarketsForMorphoVaultRewards[base.id]?.includes(hyperdrive.address)
) {
const vaultReward: Reward = {
id: "MorphoVault",
name: morphoVaultReward?.asset.name ?? "WELL",
iconUrl: WELL_ICON_URL,
amount: morphoVaultReward?.supplyApr
? `${(morphoVaultReward.supplyApr * 100).toFixed(2)}%`
: "0%",
};
rewards.push(vaultReward);
}

// Add any linea rewards for this market
if (
Expand All @@ -103,19 +116,5 @@ export function useRewards(hyperdrive: HyperdriveConfig): Reward[] | undefined {
rewards.push(lineaReward);
}

if (
eligibleMarketsForMorphoVaultRewards[base.id]?.includes(hyperdrive.address)
) {
const vaultReward: Reward = {
id: "MorphoVault",
name: morphoVaultReward?.asset.name ?? "WELL",
iconUrl: WELL_ICON_URL,
amount: morphoVaultReward?.supplyApr
? `${(morphoVaultReward.supplyApr * 100).toFixed(2)}%`
: "0%",
};
rewards.push(vaultReward);
}

return rewards;
}
Loading