Skip to content
Open
Show file tree
Hide file tree
Changes from 5 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
1 change: 0 additions & 1 deletion components/v1/MarketDetailPage/VaultInformationCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import { Metadata } from "../MarketMetadata";
import { useMarket } from "../swr/useMarket";
import ToastError from "../../../uikit/toasts/Error";
import { DEFAULT_CHAIN, useWalletContext } from "../Wallet";
import MyAssetCard from "./LeveragedTokenMyAssetCard";

/**
* VaultInformationCardProps is a React Component properties that passed to React Component VaultInformationCard
Expand Down
7 changes: 3 additions & 4 deletions modules/tokenPage/TokenPageContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import TabsList from "./component/TabsList";
import TabsContentGrid from "./component/TabsContentGrid";
import PriceInfoCard from "./component/PriceInfoCard";
import LeveragedTokenBackingCard from "./component/LeveragedTokenBackingCard";
import LeveragedTokenInfoCard from "./component/LeveragedTokenInfoCard";
import MyAssetsCard from "./component/MyAssetsCard";
import LeveragedTokenInfoCard from "./component/TokenInformation/LeveragedTokenInfoCard";
import VaultInfoCard from "./component/VaultInfoCard";
import { Root as TabsRoot } from "@radix-ui/react-tabs";
import { FunctionComponent } from "react";
import { Calculator } from "./component/Calculator";

type TokenPageContainerProps = {
chainID: number;
Expand Down Expand Up @@ -44,8 +44,8 @@ const TokenPageContainer: FunctionComponent<TokenPageContainerProps> = ({ chainI

{/* Right Column */}
<div className="flex max-w-[540px] flex-col space-y-6">
<MyAssetsCard chainID={chainID} address={tokenAddress} />
<LeveragedTokenInfoCard chainID={chainID} address={tokenAddress} />
<Calculator />
<LeveragedTokenBackingCard chainID={chainID} address={tokenAddress} />
</div>
</TabsContentGrid>
Expand All @@ -57,7 +57,6 @@ const TokenPageContainer: FunctionComponent<TokenPageContainerProps> = ({ chainI

{/* RightColumn */}
<div className="max-w-[540px] flex-col space-y-6">
<MyAssetsCard chainID={chainID} isVault address={tokenAddress} />
<VaultInfoCard chainID={chainID} address={tokenAddress} />
</div>
</TabsContentGrid>
Expand Down
26 changes: 18 additions & 8 deletions modules/tokenPage/component/ButtonMintOrRedeem.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { FunctionComponent } from "react";
import { FunctionComponent, useCallback, useState } from "react";
import * as Dialog from "@radix-ui/react-dialog";
import * as Tabs from "@radix-ui/react-tabs";
import { Metadata } from "./MarketMetadata";
import MintDialogContent from "./MintDialogContent";
import RedeemDialogContent from "./RedeemDialogContent";
import ButtonAlternate from "../../../uikit/button/ButtonAlternate";
import { customChains } from "../../../components/v1/Wallet";
import { useHotkeys } from "react-hotkeys-hook";

/**
* ButtonMintOrRedeemProps is a React Component properties that passed to React Component ButtonMintOrRedeem
Expand All @@ -20,15 +21,24 @@ type ButtonMintOrRedeemProps = {
*
* @link https://fettblog.eu/typescript-react/components/#functional-components
*/
const ButtonMintOrRedeem: FunctionComponent<ButtonMintOrRedeemProps> = ({ chainID, address }) => {
function ButtonMintOrRedeem({ chainID, address }: ButtonMintOrRedeemProps) {
const metadata = Metadata[chainID][address];
const [isOpen, setIsOpen] = useState(false);

useHotkeys("shift+s", () => setIsOpen(true));
useHotkeys("esc", () => setIsOpen(false));

return (
<Dialog.Root>
<Dialog.Root open={isOpen}>
<Dialog.Trigger asChild>
<ButtonAlternate type={chainID === customChains.bsc.id ? "bsc" : "arb"} className="w-full">
Mint or Redeem
</ButtonAlternate>
<div className="flex align-middle">
<ButtonAlternate onClick={() => setIsOpen(true)} className="mr-4 flex-1" type={chainID === customChains.bsc.id ? "bsc" : "arb"}>
Swap
</ButtonAlternate>
<span className="hidden self-center text-xs text-gray-dark-9 md:block">
Press <kbd>&#8593;</kbd> + <kbd>S</kbd> for quick shortcut
</span>
</div>
</Dialog.Trigger>
<Dialog.Overlay className="fixed inset-0 z-30 bg-gray-dark-1/60 backdrop-blur dark:bg-black/60" />
<Dialog.Content className="fixed left-0 bottom-0 z-30 w-screen sm:flex sm:h-screen sm:items-center ">
Expand All @@ -44,7 +54,7 @@ const ButtonMintOrRedeem: FunctionComponent<ButtonMintOrRedeemProps> = ({ chainI
<h1 className="m-0 text-base font-bold tracking-[-0.02em] text-gray-light-12 dark:text-gray-dark-12">{metadata.title}</h1>
</div>
</div>
<Dialog.Close asChild>
<Dialog.Close asChild onClick={() => setIsOpen(false)}>
<button className="button basic h-8 p-0">
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg" className="m-[9.5px] h-[11px] w-[11px] fill-gray-light-12 dark:fill-gray-dark-12">
<path
Expand Down Expand Up @@ -78,6 +88,6 @@ const ButtonMintOrRedeem: FunctionComponent<ButtonMintOrRedeemProps> = ({ chainI
</Dialog.Content>
</Dialog.Root>
);
};
}

export default ButtonMintOrRedeem;
41 changes: 41 additions & 0 deletions modules/tokenPage/component/Calculator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { InformationCardTitle, InformationCard, InformationCardSubTitle } from "../../../uikit/card/InformationCard";
import { Dash, TextLeftDash, TextRightDash } from "../../../uikit/Dash";

function Calculator() {
return (
<InformationCard>
<InformationCardTitle>Calulate My Profit</InformationCardTitle>
<InformationCardSubTitle>Let&#180;s try to simulate how much you&#180;ll get if the ETH price is higher or lower when you invested some ETH</InformationCardSubTitle>
<Dash>
<TextLeftDash className="text-xs font-semibold text-white">You Want To Buy</TextLeftDash>
</Dash>
<div className=" rounded-xl bg-gray-dark-3 p-3 px-2">
<div className="flex justify-between">
<div>
<div className="max-w-fit rounded-lg bg-gray-dark-2 py-2 px-1">
<h3 className=" text-xs font-bold text-white">ETH</h3>
</div>
<span className="text-xs text-gray-dark-10">Mkt. Price $2,380.23</span>
</div>
<div className="flex-col justify-center self-center">
<input type="number" className="max-h-[32px] max-w-[60px] self-center rounded-lg bg-gray-dark-2 text-right text-[16px] font-bold text-white"></input>
<p className="pt-2 text-right text-xs text-gray-dark-10">$2,800</p>
</div>
{
// TODO: add slider
}
</div>
</div>
<Dash>
<TextLeftDash className="text-xs font-semibold text-white">Expected Market Price</TextLeftDash>
<TextRightDash className="text-sm font-bold text-gray-dark-12">$3,450.34</TextRightDash>
</Dash>
<Dash>
<TextLeftDash className="text-xs font-semibold text-white ">Est. Net Profit Gain</TextLeftDash>
<TextRightDash className="text-sm font-bold text-green-dark-11">+$2,800.00</TextRightDash>
</Dash>
</InformationCard>
);
}

export { Calculator };
129 changes: 80 additions & 49 deletions modules/tokenPage/component/LeveragedTokenBackingCard.tsx
Original file line number Diff line number Diff line change
@@ -1,73 +1,104 @@
import { ethers } from "ethers";
import type { FunctionComponent } from "react";
import { FunctionComponent, useEffect, useMemo, useState } from "react";
import { tokenBalanceFormatter } from "../../../utils/formatters";
import { Metadata } from "../../../components/v1/MarketMetadata";
import { useCollateralPerLeveragedToken } from "../../../components/v1/swr/useCollateralPerLeveragedToken";
import { useDebtPerLeveragedToken } from "../../../components/v1/swr/useDebtPerLeveragedToken";
import { getProvider } from "../../../components/v1/Wallet";
import InformationCard from "../../../uikit/card/InformationCard";
import { InformationCardExtra, InformationCardSubTitle, InformationCardTitle, InformationCard } from "../../../uikit/card/InformationCard";
import { StatusEnum } from "./TokenInformation/TokenInfoStore";

/**
* LeveragedTokenBackingCardProps is a React Component properties that passed to React Component LeveragedTokenBackingCard
*/
type LeveragedTokenBackingCardProps = {
chainID: number;
address: string;
};

/**
* LeveragedTokenBackingCard is just yet another react component
*
* @link https://fettblog.eu/typescript-react/components/#functional-components
*/
type UiType = {
status: StatusEnum;
data?: {
collateralPerLeveragedToken?: number;
debtPerLeveragedToken?: number;
};
error?: string;
};

const LeveragedTokenBackingCard: FunctionComponent<LeveragedTokenBackingCardProps> = ({ chainID, address }) => {
const provider = getProvider({ chainId: chainID });
const provider = useMemo(() => {
return getProvider({ chainId: chainID });
}, [chainID]);
const metadata = Metadata[chainID][address];
const collateralPerTokenResponse = useCollateralPerLeveragedToken({ token: address, vault: metadata.vaultAddress, provider: provider });
const debtPerTokenResponse = useDebtPerLeveragedToken({ token: address, vault: metadata.vaultAddress, provider: provider });
const [uiData, setUiData] = useState<UiType>({
status: "loading",
});

// Data
const collateral = parseFloat(ethers.utils.formatUnits(collateralPerTokenResponse.data ? collateralPerTokenResponse.data : 0, metadata.collateralDecimals));
const debt = parseFloat(ethers.utils.formatUnits(debtPerTokenResponse.data ? debtPerTokenResponse.data : 0, metadata.debtDecimals));
useEffect(() => {
if (metadata) {
if (collateralPerTokenResponse.data && debtPerTokenResponse.data) {
setUiData({
status: "loaded",
data: {
collateralPerLeveragedToken: parseFloat(ethers.utils.formatUnits(collateralPerTokenResponse.data ? collateralPerTokenResponse.data : 0, metadata.collateralDecimals)),
debtPerLeveragedToken: parseFloat(ethers.utils.formatUnits(debtPerTokenResponse.data ? debtPerTokenResponse.data : 0, metadata.debtDecimals)),
},
});
}
}
}, [collateralPerTokenResponse.data, debtPerTokenResponse.data, metadata]);

// UI states
const showLoading = collateralPerTokenResponse.isLoading || debtPerTokenResponse.isLoading ? true : false;
const showError = collateralPerTokenResponse.error || debtPerTokenResponse.error ? true : false;
const showData = !showLoading && !showError && collateralPerTokenResponse.data && debtPerTokenResponse.data ? true : false;
useEffect(() => {
if (collateralPerTokenResponse.error || debtPerTokenResponse.error) {
setUiData({
status: "error",
error: collateralPerTokenResponse?.error?.message || debtPerTokenResponse?.error?.message,
});
}
}, [collateralPerTokenResponse.error, debtPerTokenResponse.error]);

return (
<InformationCard>
<div className="pt-4">
<h2 className="text-base font-bold leading-4 text-gray-light-12 dark:text-gray-dark-12">Backing per {metadata.title}</h2>
</div>
<div className="">
<p className="text-sm leading-6 text-gray-light-10 dark:text-gray-dark-10">{metadata.title} represents collaterized debt position and can be redeemed at any time.</p>
</div>
<div className="flex flex-col space-y-6">
<div className="flex flex-row justify-between">
<p className="text-sm leading-4 text-gray-light-10 dark:text-gray-dark-10">Asset</p>
<p className="text-sm leading-4 text-gray-light-10 dark:text-gray-dark-10">Allocation</p>
</div>

<div className="flex flex-row justify-between">
<p className="text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">{metadata.collateralSymbol}</p>
{(showLoading || showError) && <p className="h-4 w-[100px] animate-pulse rounded-lg bg-gray-light-3 dark:bg-gray-dark-3"></p>}
{showData && (
<p className="font-ibm text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">
{tokenBalanceFormatter.format(collateral)} {metadata.collateralSymbol}
</p>
)}
</div>
<div className="flex flex-row justify-between">
<p className="text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">{metadata.debtSymbol}</p>
{(showLoading || showError) && <p className="h-[16px] w-[100px] animate-pulse rounded-[8px] bg-gray-light-3 dark:bg-gray-dark-3"></p>}
{showData && (
<p className="font-ibm text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">
-{tokenBalanceFormatter.format(debt)} {metadata.debtSymbol}
</p>
)}
</div>
</div>
<InformationCardTitle>Backing per {metadata.title}</InformationCardTitle>
<InformationCardSubTitle>{metadata.title} represents collaterized debt position and can be redeemed at any time.</InformationCardSubTitle>
{
//TODO: simplify table with custom component and custom logic
}
<table className="text-right">
<thead className="bg-gray-dark-3 font-inter text-xs text-gray-dark-10 ">
<tr>
<th className="rounded-bl-lg rounded-tl-lg py-2 pl-2 text-left">Token</th>
<th className="py-2">Allocation</th>
<th className="w-[80px] rounded-br-lg rounded-tr-lg py-2 pr-2">Change</th>
</tr>
</thead>
<tbody>
<tr className="border-b-2 border-dashed border-b-gray-dark-5 px-2">
<td className="py-4 pl-2 text-left">
<p className="text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">{metadata.collateralSymbol}</p>
</td>
<td>
{uiData.status === "loading" && <p className="h-4 w-[100px] animate-pulse rounded-lg bg-gray-light-3 dark:bg-gray-dark-3"></p>}
{uiData.status === "loaded" && <p className="font-ibm text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">{tokenBalanceFormatter.format(uiData.data?.collateralPerLeveragedToken || 0)}</p>}
</td>
<td className="pr-2">{0}%</td>
</tr>
<tr>
<td className="py-4 pl-2 text-left">
<p className="text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">{metadata.debtSymbol}</p>
</td>
<td>
{uiData.status === "loading" && <p className="h-[16px] w-[100px] animate-pulse rounded-[8px] bg-gray-light-3 dark:bg-gray-dark-3"></p>}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h-[16px] h-4

rounded-[8px] to rounded-lg

{uiData.status === "loaded" && <p className="font-ibm text-sm font-semibold leading-4 tracking-[-.02em] text-gray-light-12 dark:text-gray-dark-12">-{tokenBalanceFormatter.format(uiData.data?.debtPerLeveragedToken || 0)}</p>}
</td>
<td className="pr-2">{0}%</td>
</tr>
</tbody>
</table>
<InformationCardExtra className="bg-green-dark-2">
<p className=" font-inter text-xs text-white">
&#10003; Last rebalanced at: <span className="font-semibold"> 13-01-2022 03:23AM </span>
</p>
</InformationCardExtra>
</InformationCard>
);
};
Expand Down
Loading