Skip to content
Open
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
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-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?.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