+) => {
const { wallet, connected } = useWallet();
const { onClick, children, ...rest } = props;
- return
-}
\ No newline at end of file
+ return (
+
+ );
+};
diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx
index 7633fc4..26348b5 100644
--- a/src/components/Layout/index.tsx
+++ b/src/components/Layout/index.tsx
@@ -36,9 +36,7 @@ export const AppLayout = (props: any) => {
return (
-
- {LABELS.AUDIT_WARNING}
-
+
{LABELS.AUDIT_WARNING}
toLamports(parseFloat(value), repayLiquidityMint), [value, repayLiquidityMint]);
+ const lamports = useMemo(
+ () => toLamports(parseFloat(value), repayLiquidityMint),
+ [value, repayLiquidityMint]
+ );
- const mark = wadToLamports(obligation?.info.borrowAmountWad).toNumber() / lamports * 100;
+ const mark =
+ (wadToLamports(obligation?.info.borrowAmountWad).toNumber() / lamports) *
+ 100;
const onRepay = useCallback(() => {
if (
@@ -103,8 +113,8 @@ export const RepayInput = (props: {
}}
>
- {LABELS.REPAY_QUESTION} (Currently:{" "})
- {formatNumber.format(balance)} {name})
+ {LABELS.REPAY_QUESTION} (Currently: ){formatNumber.format(balance)}{" "}
+ {name})
@@ -124,10 +134,22 @@ export const RepayInput = (props: {
/>
{name}
-
- setValue((fromLamports(wadToLamports(obligation?.info.borrowAmountWad).toNumber(), repayLiquidityMint) * val / 100).toFixed(2))} />
+
+ setValue(
+ (
+ (fromLamports(
+ wadToLamports(obligation?.info.borrowAmountWad).toNumber(),
+ repayLiquidityMint
+ ) *
+ val) /
+ 100
+ ).toFixed(2)
+ )
+ }
+ />
{LABELS.SELECT_COLLATERAL}
{
+ const chartDiv = useRef(null);
+
+ // dispose chart
+ useEffect(() => {
+ const div = chartDiv.current;
+ return () => {
+ let instance = div && echarts.getInstanceByDom(div);
+ instance && instance.dispose();
+ };
+ }, []);
+
+ const liquidityMint = useMint(props.reserve.liquidityMint);
+ const avilableLiquidity = fromLamports(
+ props.reserve.totalLiquidity.toNumber(),
+ liquidityMint
+ );
+
+ const totalBorrows = useMemo(
+ () =>
+ fromLamports(wadToLamports(props.reserve.totalBorrowsWad), liquidityMint),
+ [props.reserve, liquidityMint]
+ );
+
+ useEffect(() => {
+ if (!chartDiv.current) {
+ return;
+ }
+
+ let instance = echarts.getInstanceByDom(chartDiv.current);
+ if (!instance) {
+ instance = echarts.init(chartDiv.current as any);
+ }
+
+ const data = [
+ {
+ name: 'Available Liquidity',
+ value: avilableLiquidity,
+ tokens: avilableLiquidity,
+ },
+ {
+ name: 'Total Borrowed',
+ value: totalBorrows,
+ tokens: totalBorrows,
+ },
+ ];
+
+ instance.setOption({
+ tooltip: {
+ trigger: "item",
+ formatter: function (params: any) {
+ var val = formatUSD.format(params.value);
+ var tokenAmount = formatNumber.format(params.data.tokens);
+ return `${params.name}: \n${val}\n(${tokenAmount})`;
+ },
+ },
+ series: [
+ {
+ name: "Liquidity",
+ type: "pie",
+ radius: ['50%', '70%'],
+ top: 0,
+ bottom: 0,
+ left: 0,
+ right: 0,
+ animation: false,
+ label: {
+ fontSize: 14,
+ show: true,
+ formatter: function (params: any) {
+ var val = formatUSD.format(params.value);
+ var tokenAmount = formatNumber.format(params.data.tokens);
+ return `{c|${params.name}}\n{r|${tokenAmount}}\n{r|${val}}`;
+ },
+ rich: {
+ c: {
+ color: "#999",
+ lineHeight: 22,
+ align: "center",
+ },
+ r: {
+ color: "#999",
+ align: "right",
+ },
+ },
+ color: "rgba(255, 255, 255, 0.5)",
+ },
+ itemStyle: {
+ normal: {
+ borderColor: "#000",
+ },
+ },
+ data,
+ },
+ ],
+ });
+ }, [totalBorrows, avilableLiquidity]);
+
+ return
+}
export const ReserveStatus = (props: {
className?: string;
@@ -29,7 +135,7 @@ export const ReserveStatus = (props: {
justifyContent: "space-around",
}}
>
- TODO: Reserve Status - add chart
+
);
diff --git a/src/components/UserLendingCard/index.tsx b/src/components/UserLendingCard/index.tsx
index faa7546..f67b866 100644
--- a/src/components/UserLendingCard/index.tsx
+++ b/src/components/UserLendingCard/index.tsx
@@ -6,12 +6,10 @@ import {
useBorrowedAmount,
} from "./../../hooks";
import { LendingReserve } from "../../models/lending";
-import { formatNumber, wadToLamports } from "../../utils/utils";
+import { formatNumber } from "../../utils/utils";
import { Button, Card, Typography } from "antd";
import { Link } from "react-router-dom";
import { PublicKey } from "@solana/web3.js";
-import { cache, ParsedAccount } from "../../contexts/accounts";
-import { MintInfo } from "@solana/spl-token";
const { Text } = Typography;
diff --git a/src/components/WithdrawInput/index.tsx b/src/components/WithdrawInput/index.tsx
index c6efe8e..d5c37bc 100644
--- a/src/components/WithdrawInput/index.tsx
+++ b/src/components/WithdrawInput/index.tsx
@@ -76,9 +76,7 @@ export const WithdrawInput = (props: {
justifyContent: "space-around",
}}
>
-
- {LABELS.WITHDRAW_QUESTION}
-
+ {LABELS.WITHDRAW_QUESTION}
item.obligation.info.tokenMint.toBase58()),
- "single");
+ userObligationsByReserve.map((item) =>
+ item.obligation.info.tokenMint.toBase58()
+ ),
+ "single"
+ );
array.forEach((item, index) => {
const address = keys[index];
cache.add(new PublicKey(address), item, MintParser);
});
- setBorrowedLamports(userObligationsByReserve.reduce((result, item) => {
+ setBorrowedLamports(
+ userObligationsByReserve.reduce((result, item) => {
+ const borrowed = wadToLamports(
+ item.obligation.info.borrowAmountWad
+ ).toNumber();
- const borrowed = wadToLamports(item.obligation.info.borrowAmountWad).toNumber();
+ const owned = item.userAccounts.reduce(
+ (amount, acc) => (amount += acc.info.amount.toNumber()),
+ 0
+ );
+ const obligationMint = cache.get(
+ item.obligation.info.tokenMint
+ ) as ParsedAccount;
- const owned = item.userAccounts.reduce((amount, acc) => amount += acc.info.amount.toNumber(), 0);
- const obligationMint = cache.get(item.obligation.info.tokenMint) as ParsedAccount;
-
- result += borrowed * owned / obligationMint?.info.supply.toNumber();
- return result
-
- }, 0));
+ result += (borrowed * owned) / obligationMint?.info.supply.toNumber();
+ return result;
+ }, 0)
+ );
})();
+ }, [connection, userObligationsByReserve]);
-
- }, [userObligationsByReserve]);
-
- return { borrowed: fromLamports(borrowedLamports, liquidityMint), borrowedLamports };
+ return {
+ borrowed: fromLamports(borrowedLamports, liquidityMint),
+ borrowedLamports,
+ };
}
diff --git a/src/hooks/useLendingReserves.ts b/src/hooks/useLendingReserves.ts
index 1c728c9..a8e6600 100644
--- a/src/hooks/useLendingReserves.ts
+++ b/src/hooks/useLendingReserves.ts
@@ -41,7 +41,7 @@ export function useLendingReserve(address?: string | PublicKey) {
>();
useEffect(() => {
- setReserveAccount(cache.get(id || ''));
+ setReserveAccount(cache.get(id || ""));
const dispose = cache.emitter.onCache((args) => {
if (args.id === id) {
diff --git a/src/hooks/useUserObligationByReserve.ts b/src/hooks/useUserObligationByReserve.ts
index 7d9ce4b..fe7b7cc 100644
--- a/src/hooks/useUserObligationByReserve.ts
+++ b/src/hooks/useUserObligationByReserve.ts
@@ -5,14 +5,12 @@ import { PublicKey } from "@solana/web3.js";
export function useUserObligationByReserve(reserve?: string | PublicKey) {
const { userObligations } = useUserObligations();
- const userObligationsByReserve = useMemo(
- () => {
- const id = typeof reserve === 'string' ? reserve : reserve?.toBase58();
- return userObligations.filter((item) =>
- item.obligation.info.borrowReserve.toBase58() === id
- )
- }, [reserve, userObligations]
- );
+ const userObligationsByReserve = useMemo(() => {
+ const id = typeof reserve === "string" ? reserve : reserve?.toBase58();
+ return userObligations.filter(
+ (item) => item.obligation.info.borrowReserve.toBase58() === id
+ );
+ }, [reserve, userObligations]);
return {
userObligationsByReserve,
diff --git a/src/models/lending/reserve.ts b/src/models/lending/reserve.ts
index 428d199..aea1e48 100644
--- a/src/models/lending/reserve.ts
+++ b/src/models/lending/reserve.ts
@@ -262,21 +262,26 @@ export const withdrawInstruction = (
};
export const calculateBorrowAPY = (reserve: LendingReserve) => {
- const totalBorrows = reserve.totalBorrowsWad.div(WAD).toNumber()
- const currentUtilization = totalBorrows / (reserve.totalLiquidity.toNumber() + totalBorrows)
- const optimalUtilization = reserve.config.optimalUtilizationRate
+ const totalBorrows = reserve.totalBorrowsWad.div(WAD).toNumber();
+ const currentUtilization =
+ totalBorrows / (reserve.totalLiquidity.toNumber() + totalBorrows);
+ const optimalUtilization = reserve.config.optimalUtilizationRate;
let borrowAPY;
if (currentUtilization < optimalUtilization) {
const normalized_factor = currentUtilization / optimalUtilization;
const optimalBorrowRate = reserve.config.optimalBorrowRate / 100;
const minBorrowRate = reserve.config.minBorrowRate / 100;
- borrowAPY = normalized_factor * (optimalBorrowRate - minBorrowRate) + minBorrowRate;
+ borrowAPY =
+ normalized_factor * (optimalBorrowRate - minBorrowRate) + minBorrowRate;
} else {
- const normalized_factor = (currentUtilization - optimalUtilization) / (100 - optimalUtilization);
+ const normalized_factor =
+ (currentUtilization - optimalUtilization) / (100 - optimalUtilization);
const optimalBorrowRate = reserve.config.optimalBorrowRate / 100;
const maxBorrowRate = reserve.config.maxBorrowRate / 100;
- borrowAPY = normalized_factor * (maxBorrowRate - optimalBorrowRate) + optimalBorrowRate;
+ borrowAPY =
+ normalized_factor * (maxBorrowRate - optimalBorrowRate) +
+ optimalBorrowRate;
}
return borrowAPY;
-}
\ No newline at end of file
+};
diff --git a/src/views/dashboard/index.tsx b/src/views/dashboard/index.tsx
index 7e594a7..a1752a6 100644
--- a/src/views/dashboard/index.tsx
+++ b/src/views/dashboard/index.tsx
@@ -2,7 +2,7 @@ import React from "react";
import { LABELS } from "../../constants";
import { useUserObligations } from "./../../hooks";
import { ObligationItem } from "./obligationItem";
-import "./style.less"
+import "./style.less";
export const DashboardView = () => {
const { userObligations } = useUserObligations();
@@ -14,12 +14,14 @@ export const DashboardView = () => {
{LABELS.DASHBOARD_TITLE_LOANS}
- {userObligations.length > 0 &&
-
{LABELS.TABLE_TITLE_ASSET}
-
{LABELS.TABLE_TITLE_LOAN_BALANCE}
-
{LABELS.TABLE_TITLE_APY}
-
{LABELS.TABLE_TITLE_ACTION}
-
}
+ {userObligations.length > 0 && (
+
+
{LABELS.TABLE_TITLE_ASSET}
+
{LABELS.TABLE_TITLE_LOAN_BALANCE}
+
{LABELS.TABLE_TITLE_APY}
+
{LABELS.TABLE_TITLE_ACTION}
+
+ )}
{userObligations.map((item) => {
return
;
})}
diff --git a/src/views/dashboard/obligationItem.tsx b/src/views/dashboard/obligationItem.tsx
index 7eb9517..bdc8cee 100644
--- a/src/views/dashboard/obligationItem.tsx
+++ b/src/views/dashboard/obligationItem.tsx
@@ -2,11 +2,7 @@ import React from "react";
import { useTokenName } from "../../hooks";
import { LendingObligation, LendingReserve } from "../../models/lending";
import { TokenIcon } from "../../components/TokenIcon";
-import {
- wadToLamports,
- formatNumber,
- fromLamports,
-} from "../../utils/utils";
+import { wadToLamports, formatNumber, fromLamports } from "../../utils/utils";
import { Button, Card } from "antd";
import { Link } from "react-router-dom";
import { cache, ParsedAccount, useMint } from "../../contexts/accounts";
@@ -30,9 +26,7 @@ export const ObligationItem = (props: {
);
return (
-
+
diff --git a/src/views/home/item.tsx b/src/views/home/item.tsx
index 4c71f29..350d611 100644
--- a/src/views/home/item.tsx
+++ b/src/views/home/item.tsx
@@ -1,13 +1,17 @@
-import React from "react";
+import React, { useMemo } from "react";
import { useTokenName } from "../../hooks";
import { calculateBorrowAPY, LendingReserve } from "../../models/lending";
import { TokenIcon } from "../../components/TokenIcon";
-import { wadToLamports, formatNumber, fromLamports } from "../../utils/utils";
+import {
+ wadToLamports,
+ formatNumber,
+ fromLamports,
+ formatPct,
+} from "../../utils/utils";
import { Card } from "antd";
import { Link } from "react-router-dom";
import { PublicKey } from "@solana/web3.js";
import { useMint } from "../../contexts/accounts";
-import { WAD } from "../../constants";
export const LendingReserveItem = (props: {
reserve: LendingReserve;
@@ -22,10 +26,15 @@ export const LendingReserveItem = (props: {
liquidityMint
);
- console.log(props.reserve.totalBorrowsWad.toString());
- const totalBorrows = fromLamports(wadToLamports(props.reserve.totalBorrowsWad), liquidityMint);
+ const totalBorrows = useMemo(
+ () =>
+ fromLamports(wadToLamports(props.reserve.totalBorrowsWad), liquidityMint),
+ [props.reserve, liquidityMint]
+ );
- console.log(liquidityMint);
+ const borrowAPY = useMemo(() => calculateBorrowAPY(props.reserve), [
+ props.reserve,
+ ]);
return (
@@ -36,18 +45,15 @@ export const LendingReserveItem = (props: {
{name}
- {formatNumber.format(totalLiquidity)} {name}
+ {formatNumber.format(totalLiquidity+totalBorrows)} {name}
{formatNumber.format(totalBorrows)} {name}
--
-
{calculateBorrowAPY(props.reserve)}
+
{formatPct.format(borrowAPY)}
);
};
-
-
-
diff --git a/src/views/repayReserve/index.tsx b/src/views/repayReserve/index.tsx
index 31a94b6..29aa820 100644
--- a/src/views/repayReserve/index.tsx
+++ b/src/views/repayReserve/index.tsx
@@ -15,9 +15,11 @@ export const RepayReserveView = () => {
reserve?: string;
obligation?: string;
}>();
-
+
const lendingObligation = useLendingObligation(obligationId);
- const lendingReserve = useLendingReserve(obligationId ? lendingObligation?.info.borrowReserve : reserveId);
+ const lendingReserve = useLendingReserve(
+ obligationId ? lendingObligation?.info.borrowReserve : reserveId
+ );
const reserve = lendingReserve?.info;
console.log([reserveId, obligationId]);