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
6 changes: 3 additions & 3 deletions apps/hyperdrive-trading/src/ui/portfolio/Portfolio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { useNavigate, useSearch } from "@tanstack/react-router";
import { ReactElement } from "react";
import { Tabs } from "src/ui/base/components/Tabs/Tabs";
import { useFeatureFlag } from "src/ui/base/featureFlags/featureFlags";
import { OpenLongsContainer } from "src/ui/portfolio/longs/OpenLongsTable/OpenLongsTableDesktop";
import { LpAndWithdrawalSharesContainer } from "src/ui/portfolio/lp/LpAndWithdrawalSharesTable/LpAndWithdrawalSharesTable";
import { OpenLongsContainer } from "src/ui/portfolio/longs/LongsContainer";
import { LpAndWithdrawalSharesContainer } from "src/ui/portfolio/lp/LpAndWithdrawalSharesContainer";
import { PORTFOLIO_ROUTE } from "src/ui/portfolio/routes";
import { OpenShortsContainer } from "src/ui/portfolio/shorts/OpenShortsTable/OpenShortsTableDesktop";
import { OpenShortsContainer } from "src/ui/portfolio/shorts/ShortsContainer";

export function Portfolio(): ReactElement {
const { position } = useSearch({ from: PORTFOLIO_ROUTE });
Expand Down
13 changes: 13 additions & 0 deletions apps/hyperdrive-trading/src/ui/portfolio/PositionContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import classNames from "classnames";
import { PropsWithChildren, ReactElement } from "react";

export function PositionContainer({
className,
children,
}: PropsWithChildren<{ className?: string }>): ReactElement {
return (
<div className={classNames("flex w-[1036px] flex-col gap-10", className)}>
{children}
</div>
);
}
29 changes: 29 additions & 0 deletions apps/hyperdrive-trading/src/ui/portfolio/PositionTableHeading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { HyperdriveConfig } from "@delvtech/hyperdrive-appconfig";
import { ReactElement, ReactNode } from "react";
import { AssetStack } from "src/ui/markets/AssetStack";

export function PositionTableHeading({
hyperdrive,
hyperdriveName,
rightElement,
}: {
hyperdrive: HyperdriveConfig;
/**
* Optional name to override the name from the hyperdrive
*/
hyperdriveName?: string;
rightElement: ReactNode;
}): ReactElement {
return (
<div className="flex items-center justify-between">
<div className="flex items-center gap-1 font-chakraPetch text-h4">
<AssetStack
hyperdriveAddress={hyperdrive.address}
hyperdriveChainId={hyperdrive.chainId}
/>
<p className="text-h4">{hyperdriveName ?? hyperdrive.name}</p>
</div>
{rightElement}
</div>
);
}
114 changes: 114 additions & 0 deletions apps/hyperdrive-trading/src/ui/portfolio/longs/LongsContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { appConfig, HyperdriveConfig } from "@delvtech/hyperdrive-appconfig";
import { Link } from "@tanstack/react-router";
import { ReactElement } from "react";
import { ExternalLink } from "src/ui/analytics/ExternalLink";
import LoadingState from "src/ui/base/components/LoadingState";
import { NonIdealState } from "src/ui/base/components/NonIdealState";
import { ConnectWalletButton } from "src/ui/compliance/ConnectWallet";
import { OpenLongsTableDesktop } from "src/ui/portfolio/longs/OpenLongsTable/OpenLongsTableDesktop";
import { TotalOpenLongsValue } from "src/ui/portfolio/longs/TotalOpenLongsValue/TotalOpenLongsValue";
import {
OpenLongPositionsData,
usePortfolioLongsData,
} from "src/ui/portfolio/longs/usePortfolioLongsData";
import { PositionContainer } from "src/ui/portfolio/PositionContainer";
import { PositionTableHeading } from "src/ui/portfolio/PositionTableHeading";
import { useAccount } from "wagmi";

export function OpenLongsContainer(): ReactElement {
const { address: account } = useAccount();
const { openLongPositions, openLongPositionsStatus } =
usePortfolioLongsData();
if (!account) {
return (
<PositionContainer className="my-28">
<NonIdealState
heading="No wallet connected"
action={<ConnectWalletButton />}
/>
</PositionContainer>
);
}

if (openLongPositionsStatus === "loading") {
return (
<PositionContainer>
<LoadingState
heading="Loading your Longs..."
text="Searching for Long events, calculating current value and PnL..."
/>
</PositionContainer>
);
}

if (openLongPositions?.every((position) => !position.openLongs.length)) {
return (
<PositionContainer className="my-28">
<NonIdealState
heading="No Longs found"
text={
<p className="max-w-xl">
Visit the{" "}
<ExternalLink
href="https://docs.hyperdrive.box/hyperdrive-overview/position-types/longs-fixed-rates"
newTab
>
documentation
</ExternalLink>{" "}
or explore pools to open your first Long position.
</p>
}
action={
<Link className="daisy-btn daisy-btn-primary rounded-full" to="/">
View Pools
</Link>
}
/>
</PositionContainer>
);
}

return (
<PositionContainer className="mt-10">
{openLongPositions &&
appConfig.hyperdrives
.filter((hyperdrive) => {
const openLongs = findOpenLongs(
openLongPositions,
hyperdrive,
)?.openLongs;
// Ensure this hyperdrive pool has open positions before rendering.
return openLongPositionsStatus === "success" && openLongs?.length;
})
.map((hyperdrive) => {
const openLongs = findOpenLongs(
openLongPositions,
hyperdrive,
)?.openLongs;
return (
<div className="flex flex-col gap-6" key={hyperdrive.address}>
<PositionTableHeading
hyperdrive={hyperdrive}
rightElement={<TotalOpenLongsValue hyperdrive={hyperdrive} />}
/>
<OpenLongsTableDesktop
hyperdrive={hyperdrive}
openLongs={openLongs}
/>
</div>
);
})}
</PositionContainer>
);
}

function findOpenLongs(
openLongPositions: OpenLongPositionsData,
hyperdrive: HyperdriveConfig,
) {
return openLongPositions.find(
(position) =>
position.hyperdrive.address === hyperdrive.address &&
position.hyperdrive.chainId === hyperdrive.chainId,
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@ import {
AppConfig,
appConfig,
getBaseToken,
getToken,
HyperdriveConfig,
} from "@delvtech/hyperdrive-appconfig";
import {
calculateAprFromPrice,
OpenLongPositionReceived,
} from "@delvtech/hyperdrive-js";
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/outline";
import { Link } from "@tanstack/react-router";
import {
createColumnHelper,
flexRender,
Expand All @@ -24,7 +22,6 @@ import { ReactElement } from "react";
import { calculateAnnualizedPercentageChange } from "src/base/calculateAnnualizedPercentageChange";
import { convertMillisecondsToDays } from "src/base/convertMillisecondsToDays";
import { formatRate } from "src/base/formatRate";
import LoadingState from "src/ui/base/components/LoadingState";
import { NonIdealState } from "src/ui/base/components/NonIdealState";
import { Pagination } from "src/ui/base/components/Pagination";
import { formatBalance } from "src/ui/base/formatting/formatBalance";
Expand All @@ -33,126 +30,9 @@ import { MaturesOnCell } from "src/ui/hyperdrive/MaturesOnCell/MaturesOnCell";
import { CloseLongModalButton } from "src/ui/hyperdrive/longs/CloseLongModalButton/CloseLongModalButton";
import { StatusCell } from "src/ui/hyperdrive/longs/StatusCell";
import { CurrentValueCell } from "src/ui/portfolio/longs/OpenLongsTable/CurrentValueCell";
import { TotalOpenLongsValue } from "src/ui/portfolio/longs/OpenLongsTable/TotalOpenLongsValue";
import { usePortfolioLongsData } from "src/ui/portfolio/longs/usePortfolioLongsData";
import { useAccount } from "wagmi";
import { ManageLongsButton } from "./ManageLongsButton";

export function OpenLongsContainer(): ReactElement {
const { address: account } = useAccount();
const { openLongPositions, openLongPositionsStatus } =
usePortfolioLongsData();
if (!account) {
return (
<div className="my-28 flex w-[1036px] flex-col gap-10">
<NonIdealState
heading="No wallet connected"
action={<ConnectWalletButton />}
/>
</div>
);
}

if (openLongPositionsStatus === "loading") {
return (
<div className="flex w-[1036px] flex-col gap-10">
<LoadingState
heading="Loading your Longs..."
text="Searching for Long events, calculating current value and PnL..."
/>
</div>
);
}

if (openLongPositions?.every((position) => position.openLongs.length === 0)) {
return (
<div className="my-28 flex w-[1036px] flex-col gap-10">
<NonIdealState
heading="No Longs found"
text={
<p className="max-w-xl">
Visit the{" "}
<a
className="daisy-link"
href="https://docs.hyperdrive.box/hyperdrive-overview/position-types/longs-fixed-rates"
rel="noopener noreferrer"
target="_blank"
>
documentation
</a>{" "}
or explore pools to open your first Long position.
</p>
}
action={
<Link className="daisy-btn daisy-btn-primary rounded-full" to="/">
View Pools
</Link>
}
/>
</div>
);
}

return (
<div className="mt-10 flex w-[1036px] flex-col gap-10">
{appConfig.hyperdrives.map((hyperdrive) => {
const openLongs = openLongPositions?.find(
(position) =>
position.hyperdrive.address === hyperdrive.address &&
position.hyperdrive.chainId === hyperdrive.chainId,
)?.openLongs;
const baseToken = getBaseToken({
hyperdriveChainId: hyperdrive.chainId,
hyperdriveAddress: hyperdrive.address,
appConfig,
});
const sharesToken = getToken({
chainId: hyperdrive.chainId,
tokenAddress: hyperdrive.poolConfig.vaultSharesToken,
appConfig,
});
// Ensure this hyperdrive pool has open positions before rendering.
if (openLongPositionsStatus === "success" && !openLongs?.length) {
return null;
}
return (
<div className="flex flex-col gap-6" key={hyperdrive.address}>
<div className="flex items-center justify-between">
<div className="flex items-center gap-1 font-chakraPetch text-h4">
<div className="daisy-avatar-group inline-flex justify-center -space-x-6 overflow-visible rtl:space-x-reverse">
{hyperdrive.depositOptions.isBaseTokenDepositEnabled ? (
<div
className="daisy-avatar daisy-tooltip daisy-tooltip-bottom w-12 scale-75 overflow-visible sm:scale-100"
data-tip={baseToken.symbol}
>
<img src={baseToken.iconUrl} className="rounded-full" />
</div>
) : null}
{sharesToken &&
hyperdrive.depositOptions.isShareTokenDepositsEnabled ? (
<div
className="daisy-avatar daisy-tooltip daisy-tooltip-bottom w-12 scale-75 overflow-visible sm:scale-100"
data-tip={sharesToken.symbol}
>
<img src={sharesToken.iconUrl} className="rounded-full" />
</div>
) : null}
</div>
<p className="text-h4">{hyperdrive.name}</p>
</div>
<TotalOpenLongsValue hyperdrive={hyperdrive} />
</div>
<OpenLongsTableDesktop
hyperdrive={hyperdrive}
openLongs={openLongs}
/>
</div>
);
})}
</div>
);
}

export function OpenLongsTableDesktop({
hyperdrive,
openLongs,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { getDrift } from "src/drift/getDrift";
import { useAppConfigForConnectedChain } from "src/ui/appconfig/useAppConfigForConnectedChain";
import { useAccount } from "wagmi";

type OpenLongPositionsData = {
export type OpenLongPositionsData = {
hyperdrive: HyperdriveConfig;
openLongs: OpenLongPositionReceived[];
}[];
Expand Down
Loading
Loading