mirror of https://github.com/certusone/oyster.git
feat: borrow amount Type
This commit is contained in:
parent
49324447ba
commit
00db4555be
|
@ -23,18 +23,21 @@ import {
|
||||||
LendingObligationLayout,
|
LendingObligationLayout,
|
||||||
borrowInstruction,
|
borrowInstruction,
|
||||||
LendingMarket,
|
LendingMarket,
|
||||||
|
BorrowAmountType,
|
||||||
|
LendingObligation,
|
||||||
} from "../models";
|
} from "../models";
|
||||||
import { toLamports } from "../utils/utils";
|
import { toLamports } from "../utils/utils";
|
||||||
|
|
||||||
export const borrow = async (
|
export const borrow = async (
|
||||||
from: TokenAccount,
|
from: TokenAccount,
|
||||||
amount: number,
|
amount: number,
|
||||||
|
amountType: BorrowAmountType,
|
||||||
|
|
||||||
borrowReserve: LendingReserve,
|
borrowReserve: ParsedAccount<LendingReserve>,
|
||||||
borrowReserveAddress: PublicKey,
|
|
||||||
|
|
||||||
depositReserve: LendingReserve,
|
depositReserve: ParsedAccount<LendingReserve>,
|
||||||
depositReserveAddress: PublicKey,
|
|
||||||
|
exsistingObligation: ParsedAccount<LendingObligation> | undefined,
|
||||||
|
|
||||||
connection: Connection,
|
connection: Connection,
|
||||||
wallet: any
|
wallet: any
|
||||||
|
@ -82,7 +85,7 @@ export const borrow = async (
|
||||||
instructions,
|
instructions,
|
||||||
cleanupInstructions,
|
cleanupInstructions,
|
||||||
accountRentExempt,
|
accountRentExempt,
|
||||||
borrowReserve.liquidityMint,
|
borrowReserve.info.liquidityMint,
|
||||||
signers
|
signers
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -108,23 +111,44 @@ export const borrow = async (
|
||||||
cleanupInstructions = [];
|
cleanupInstructions = [];
|
||||||
|
|
||||||
const [authority] = await PublicKey.findProgramAddress(
|
const [authority] = await PublicKey.findProgramAddress(
|
||||||
[depositReserve.lendingMarket.toBuffer()],
|
[depositReserve.info.lendingMarket.toBuffer()],
|
||||||
LENDING_PROGRAM_ID
|
LENDING_PROGRAM_ID
|
||||||
);
|
);
|
||||||
|
|
||||||
const mint = (await cache.query(
|
|
||||||
connection,
|
|
||||||
depositReserve.collateralMint,
|
let amountLamports: number = 0;
|
||||||
MintParser
|
let fromLamports: number = 0;
|
||||||
)) as ParsedAccount<MintInfo>;
|
if(amountType === BorrowAmountType.LiquidityBorrowAmount) {
|
||||||
const amountLamports = toLamports(amount, mint?.info);
|
// approve max transfer
|
||||||
|
// TODO: improve contrain by using dex market data
|
||||||
|
const approvedAmount = from.info.amount.toNumber();
|
||||||
|
|
||||||
|
fromLamports = approvedAmount - accountRentExempt;
|
||||||
|
|
||||||
|
const mint = (await cache.query(
|
||||||
|
connection,
|
||||||
|
borrowReserve.info.liquidityMint,
|
||||||
|
MintParser
|
||||||
|
)) as ParsedAccount<MintInfo>;
|
||||||
|
|
||||||
|
amountLamports = toLamports(amount, mint?.info);
|
||||||
|
} else if(amountType === BorrowAmountType.CollateralDepositAmount) {
|
||||||
|
const mint = (await cache.query(
|
||||||
|
connection,
|
||||||
|
depositReserve.info.collateralMint,
|
||||||
|
MintParser
|
||||||
|
)) as ParsedAccount<MintInfo>;
|
||||||
|
amountLamports = toLamports(amount, mint?.info);
|
||||||
|
fromLamports = amountLamports;
|
||||||
|
}
|
||||||
|
|
||||||
const fromAccount = ensureSplAccount(
|
const fromAccount = ensureSplAccount(
|
||||||
instructions,
|
instructions,
|
||||||
cleanupInstructions,
|
cleanupInstructions,
|
||||||
from,
|
from,
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
amountLamports + accountRentExempt,
|
fromLamports + accountRentExempt,
|
||||||
signers
|
signers
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -136,17 +160,17 @@ export const borrow = async (
|
||||||
authority,
|
authority,
|
||||||
wallet.publicKey,
|
wallet.publicKey,
|
||||||
[],
|
[],
|
||||||
amountLamports
|
fromLamports
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
const market = cache.get(depositReserve.lendingMarket) as ParsedAccount<
|
const market = cache.get(depositReserve.info.lendingMarket) as ParsedAccount<
|
||||||
LendingMarket
|
LendingMarket
|
||||||
>;
|
>;
|
||||||
|
|
||||||
const dexMarketAddress = borrowReserve.dexMarketOption
|
const dexMarketAddress = borrowReserve.info.dexMarketOption
|
||||||
? borrowReserve.dexMarket
|
? borrowReserve.info.dexMarket
|
||||||
: depositReserve.dexMarket;
|
: depositReserve.info.dexMarket;
|
||||||
const dexMarket = cache.get(dexMarketAddress);
|
const dexMarket = cache.get(dexMarketAddress);
|
||||||
|
|
||||||
if (!dexMarket) {
|
if (!dexMarket) {
|
||||||
|
@ -154,7 +178,7 @@ export const borrow = async (
|
||||||
}
|
}
|
||||||
|
|
||||||
const dexOrderBookSide = market.info.quoteMint.equals(
|
const dexOrderBookSide = market.info.quoteMint.equals(
|
||||||
depositReserve.liquidityMint
|
depositReserve.info.liquidityMint
|
||||||
)
|
)
|
||||||
? dexMarket?.info.bids
|
? dexMarket?.info.bids
|
||||||
: dexMarket?.info.asks;
|
: dexMarket?.info.asks;
|
||||||
|
@ -169,12 +193,13 @@ export const borrow = async (
|
||||||
instructions.push(
|
instructions.push(
|
||||||
borrowInstruction(
|
borrowInstruction(
|
||||||
amountLamports,
|
amountLamports,
|
||||||
|
amountType,
|
||||||
fromAccount,
|
fromAccount,
|
||||||
toAccount,
|
toAccount,
|
||||||
depositReserveAddress,
|
depositReserve.pubkey,
|
||||||
depositReserve.collateralSupply,
|
depositReserve.info.collateralSupply,
|
||||||
borrowReserveAddress,
|
borrowReserve.pubkey,
|
||||||
borrowReserve.liquiditySupply,
|
borrowReserve.info.liquiditySupply,
|
||||||
|
|
||||||
obligation,
|
obligation,
|
||||||
obligationMint,
|
obligationMint,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React, { useCallback, useMemo, useState } from "react";
|
import React, { useCallback, useMemo, useState } from "react";
|
||||||
import { useTokenName, useUserBalance } from "../../hooks";
|
import { useTokenName, useUserBalance } from "../../hooks";
|
||||||
import { LendingReserve, LendingReserveParser } from "../../models";
|
import { BorrowAmountType, LendingReserve, LendingReserveParser } from "../../models";
|
||||||
import { TokenIcon } from "../TokenIcon";
|
import { TokenIcon } from "../TokenIcon";
|
||||||
import { Button, Card } from "antd";
|
import { Button, Card } from "antd";
|
||||||
import { cache, ParsedAccount } from "../../contexts/accounts";
|
import { cache, ParsedAccount } from "../../contexts/accounts";
|
||||||
|
@ -15,15 +15,13 @@ import { LABELS } from "../../constants";
|
||||||
|
|
||||||
export const BorrowInput = (props: {
|
export const BorrowInput = (props: {
|
||||||
className?: string;
|
className?: string;
|
||||||
reserve: LendingReserve;
|
reserve: ParsedAccount<LendingReserve>;
|
||||||
address: PublicKey;
|
|
||||||
}) => {
|
}) => {
|
||||||
const connection = useConnection();
|
const connection = useConnection();
|
||||||
const { wallet } = useWallet();
|
const { wallet } = useWallet();
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
|
|
||||||
const borrowReserve = props.reserve;
|
const borrowReserve = props.reserve;
|
||||||
const borrowReserveAddress = props.address;
|
|
||||||
|
|
||||||
const [collateralReserveMint, setCollateralReserveMint] = useState<string>();
|
const [collateralReserveMint, setCollateralReserveMint] = useState<string>();
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ export const BorrowInput = (props: {
|
||||||
return cache.get(id) as ParsedAccount<LendingReserve>;
|
return cache.get(id) as ParsedAccount<LendingReserve>;
|
||||||
}, [collateralReserveMint]);
|
}, [collateralReserveMint]);
|
||||||
|
|
||||||
const name = useTokenName(borrowReserve?.liquidityMint);
|
const name = useTokenName(borrowReserve?.info.liquidityMint);
|
||||||
const { accounts: fromAccounts } = useUserBalance(
|
const { accounts: fromAccounts } = useUserBalance(
|
||||||
collateralReserve?.info.collateralMint
|
collateralReserve?.info.collateralMint
|
||||||
);
|
);
|
||||||
|
@ -50,10 +48,11 @@ export const BorrowInput = (props: {
|
||||||
borrow(
|
borrow(
|
||||||
fromAccounts[0],
|
fromAccounts[0],
|
||||||
parseFloat(value),
|
parseFloat(value),
|
||||||
|
// TODO: switch to collateral when user is using slider
|
||||||
|
BorrowAmountType.LiquidityBorrowAmount,
|
||||||
borrowReserve,
|
borrowReserve,
|
||||||
borrowReserveAddress,
|
collateralReserve,
|
||||||
collateralReserve.info,
|
undefined,
|
||||||
collateralReserve.pubkey,
|
|
||||||
connection,
|
connection,
|
||||||
wallet
|
wallet
|
||||||
);
|
);
|
||||||
|
@ -64,7 +63,6 @@ export const BorrowInput = (props: {
|
||||||
collateralReserve,
|
collateralReserve,
|
||||||
borrowReserve,
|
borrowReserve,
|
||||||
fromAccounts,
|
fromAccounts,
|
||||||
borrowReserveAddress,
|
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const bodyStyle: React.CSSProperties = {
|
const bodyStyle: React.CSSProperties = {
|
||||||
|
@ -86,7 +84,7 @@ export const BorrowInput = (props: {
|
||||||
>
|
>
|
||||||
<div className="borrow-input-title">{LABELS.BORROW_QUESTION}</div>
|
<div className="borrow-input-title">{LABELS.BORROW_QUESTION}</div>
|
||||||
<div className="token-input">
|
<div className="token-input">
|
||||||
<TokenIcon mintAddress={borrowReserve?.liquidityMint} />
|
<TokenIcon mintAddress={borrowReserve?.info.liquidityMint} />
|
||||||
<NumericInput
|
<NumericInput
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(val: any) => {
|
onChange={(val: any) => {
|
||||||
|
@ -105,7 +103,7 @@ export const BorrowInput = (props: {
|
||||||
</div>
|
</div>
|
||||||
<div className="borrow-input-title">{LABELS.SELECT_COLLATERAL}</div>
|
<div className="borrow-input-title">{LABELS.SELECT_COLLATERAL}</div>
|
||||||
<CollateralSelector
|
<CollateralSelector
|
||||||
reserve={borrowReserve}
|
reserve={borrowReserve.info}
|
||||||
mint={collateralReserveMint}
|
mint={collateralReserveMint}
|
||||||
onMintChange={setCollateralReserveMint}
|
onMintChange={setCollateralReserveMint}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -20,13 +20,13 @@ export const ReserveUtilizationChart = (props: {
|
||||||
|
|
||||||
const liquidityMint = useMint(props.reserve.liquidityMint);
|
const liquidityMint = useMint(props.reserve.liquidityMint);
|
||||||
const avilableLiquidity = fromLamports(
|
const avilableLiquidity = fromLamports(
|
||||||
props.reserve.totalLiquidity.toNumber(),
|
props.reserve.availableLiqudity.toNumber(),
|
||||||
liquidityMint
|
liquidityMint
|
||||||
);
|
);
|
||||||
|
|
||||||
const totalBorrows = useMemo(
|
const totalBorrows = useMemo(
|
||||||
() =>
|
() =>
|
||||||
fromLamports(wadToLamports(props.reserve.totalBorrowsWad), liquidityMint),
|
fromLamports(wadToLamports(props.reserve.borrowedLiquidityWad), liquidityMint),
|
||||||
[props.reserve, liquidityMint]
|
[props.reserve, liquidityMint]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { LendingReserve } from "../../models/lending";
|
||||||
import { TokenIcon } from "../../components/TokenIcon";
|
import { TokenIcon } from "../../components/TokenIcon";
|
||||||
import { formatNumber, formatPct, fromLamports } from "../../utils/utils";
|
import { formatNumber, formatPct, fromLamports } from "../../utils/utils";
|
||||||
import { Card, Typography } from "antd";
|
import { Card, Typography } from "antd";
|
||||||
import { useMint } from "../../contexts/accounts";
|
import { ParsedAccount, useMint } from "../../contexts/accounts";
|
||||||
import { PublicKey } from "@solana/web3.js";
|
import { PublicKey } from "@solana/web3.js";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
|
|
||||||
|
@ -17,17 +17,16 @@ export enum SideReserveOverviewMode {
|
||||||
|
|
||||||
export const SideReserveOverview = (props: {
|
export const SideReserveOverview = (props: {
|
||||||
className?: string;
|
className?: string;
|
||||||
reserve: LendingReserve;
|
reserve: ParsedAccount<LendingReserve>;
|
||||||
address: PublicKey;
|
|
||||||
mode: SideReserveOverviewMode;
|
mode: SideReserveOverviewMode;
|
||||||
}) => {
|
}) => {
|
||||||
const reserve = props.reserve;
|
const reserve = props.reserve.info;
|
||||||
const mode = props.mode;
|
const mode = props.mode;
|
||||||
const name = useTokenName(reserve?.liquidityMint);
|
const name = useTokenName(reserve?.liquidityMint);
|
||||||
const liquidityMint = useMint(props.reserve.liquidityMint);
|
const liquidityMint = useMint(reserve.liquidityMint);
|
||||||
|
|
||||||
const totalLiquidity = fromLamports(
|
const availableLiqudity = fromLamports(
|
||||||
props.reserve.totalLiquidity.toNumber(),
|
reserve.availableLiqudity.toNumber(),
|
||||||
liquidityMint
|
liquidityMint
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -102,7 +101,7 @@ export const SideReserveOverview = (props: {
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Link to={`/reserve/${props.address}`}>
|
<Link to={`/reserve/${props.reserve.pubkey}`}>
|
||||||
<TokenIcon
|
<TokenIcon
|
||||||
mintAddress={reserve?.liquidityMint}
|
mintAddress={reserve?.liquidityMint}
|
||||||
style={{ width: 30, height: 30 }}
|
style={{ width: 30, height: 30 }}
|
||||||
|
@ -124,7 +123,7 @@ export const SideReserveOverview = (props: {
|
||||||
Available liquidity:
|
Available liquidity:
|
||||||
</Text>
|
</Text>
|
||||||
<div className="card-cell ">
|
<div className="card-cell ">
|
||||||
{formatNumber.format(totalLiquidity)} {name}
|
{formatNumber.format(availableLiqudity)} {name}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -21,9 +21,14 @@ export const LABELS = {
|
||||||
BORROW_QUESTION: "How much would you like to borrow?",
|
BORROW_QUESTION: "How much would you like to borrow?",
|
||||||
BORROW_ACTION: "Borrow",
|
BORROW_ACTION: "Borrow",
|
||||||
TABLE_TITLE_ASSET: "Asset",
|
TABLE_TITLE_ASSET: "Asset",
|
||||||
TABLE_TITLE_LOAN_BALANCE: "Your loan balan",
|
TABLE_TITLE_LOAN_BALANCE: "Your loan balance",
|
||||||
|
TABLE_TITLE_DEPOSIT_BALANCE: "Your deposit balane",
|
||||||
TABLE_TITLE_APY: "APY",
|
TABLE_TITLE_APY: "APY",
|
||||||
TABLE_TITLE_APR: "APR",
|
TABLE_TITLE_APR: "APR",
|
||||||
|
TABLE_TITLE_BORROW_APR: "Borrow APR",
|
||||||
|
TABLE_TITLE_DEPOSIT_APR: "Deposit APY",
|
||||||
|
TABLE_TITLE_TOTAL_BORROWED: "Total Borrowed",
|
||||||
|
TABLE_TITLE_MARKET_SIZE: "Market Size",
|
||||||
TABLE_TITLE_ACTION: "Action",
|
TABLE_TITLE_ACTION: "Action",
|
||||||
TABLE_TITLE_MAX_BORROW: "Available fro you",
|
TABLE_TITLE_MAX_BORROW: "Available fro you",
|
||||||
DASHBOARD_TITLE_LOANS: "Loans",
|
DASHBOARD_TITLE_LOANS: "Loans",
|
||||||
|
|
|
@ -8,3 +8,4 @@ export * from "./useLendingObligations";
|
||||||
export * from "./useUserObligations";
|
export * from "./useUserObligations";
|
||||||
export * from "./useUserObligationByReserve";
|
export * from "./useUserObligationByReserve";
|
||||||
export * from "./useBorrowedAmount";
|
export * from "./useBorrowedAmount";
|
||||||
|
export * from "./useUserDeposits";
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
|
import { PublicKey } from "@solana/web3.js";
|
||||||
import { useMint } from "../contexts/accounts";
|
import { useMint } from "../contexts/accounts";
|
||||||
import { LendingReserve } from "../models/lending";
|
import { LendingReserve } from "../models/lending";
|
||||||
import { fromLamports } from "../utils/utils";
|
import { fromLamports } from "../utils/utils";
|
||||||
import { useUserBalance } from "./useUserBalance";
|
import { useUserBalance } from "./useUserBalance";
|
||||||
|
|
||||||
export function useCollateralBalance(reserve?: LendingReserve) {
|
export function useCollateralBalance(reserve?: LendingReserve, account?: PublicKey) {
|
||||||
const mint = useMint(reserve?.collateralMint);
|
const mint = useMint(reserve?.collateralMint);
|
||||||
const { balanceLamports, accounts } = useUserBalance(reserve?.collateralMint);
|
const { balanceLamports, accounts } = useUserBalance(reserve?.collateralMint, account);
|
||||||
|
|
||||||
const collateralRatioLamports =
|
const collateralRatioLamports =
|
||||||
(reserve?.totalLiquidity.toNumber() || 0) *
|
(reserve?.availableLiqudity.toNumber() || 0) *
|
||||||
(balanceLamports / (reserve?.collateralMintSupply.toNumber() || 1));
|
(balanceLamports / (reserve?.collateralMintSupply.toNumber() || 1));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -4,12 +4,12 @@ import { useMint } from "../contexts/accounts";
|
||||||
import { fromLamports } from "../utils/utils";
|
import { fromLamports } from "../utils/utils";
|
||||||
import { useUserAccounts } from "./useUserAccounts";
|
import { useUserAccounts } from "./useUserAccounts";
|
||||||
|
|
||||||
export function useUserBalance(mint?: PublicKey) {
|
export function useUserBalance(mint?: PublicKey, account?: PublicKey) {
|
||||||
const { userAccounts } = useUserAccounts();
|
const { userAccounts } = useUserAccounts();
|
||||||
const mintInfo = useMint(mint);
|
const mintInfo = useMint(mint);
|
||||||
const accounts = useMemo(() => {
|
const accounts = useMemo(() => {
|
||||||
return userAccounts
|
return userAccounts
|
||||||
.filter((acc) => mint?.equals(acc.info.mint))
|
.filter((acc) => mint?.equals(acc.info.mint) && (!account || account.equals(acc.pubkey)))
|
||||||
.sort((a, b) => b.info.amount.sub(a.info.amount).toNumber());
|
.sort((a, b) => b.info.amount.sub(a.info.amount).toNumber());
|
||||||
}, [userAccounts, mint]);
|
}, [userAccounts, mint]);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { ParsedAccount } from "../contexts/accounts";
|
||||||
|
import { LendingReserve } from "../models/lending";
|
||||||
|
import { useUserAccounts } from "./useUserAccounts";
|
||||||
|
import { useLendingReserves } from "./useLendingReserves";
|
||||||
|
import { useMemo } from "react";
|
||||||
|
|
||||||
|
export function useUserDeposits() {
|
||||||
|
const { userAccounts } = useUserAccounts();
|
||||||
|
const { reserveAccounts } = useLendingReserves();
|
||||||
|
|
||||||
|
const reservesByCollateralMint = useMemo(() => {
|
||||||
|
return reserveAccounts.reduce((result, item) => {
|
||||||
|
result.set(item.info.collateralMint.toBase58(), item);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
, new Map<string, ParsedAccount<LendingReserve>>())
|
||||||
|
}, [reserveAccounts]);
|
||||||
|
|
||||||
|
const userDeposits = useMemo(() => {
|
||||||
|
return userAccounts
|
||||||
|
.filter((acc) => reservesByCollateralMint.has(acc.info.mint.toBase58()))
|
||||||
|
.map(item => ({
|
||||||
|
account: item,
|
||||||
|
reserve: reservesByCollateralMint.get(item.info.mint.toBase58()) as ParsedAccount<LendingReserve>,
|
||||||
|
}));
|
||||||
|
}, [userAccounts, reservesByCollateralMint]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
userDeposits
|
||||||
|
};
|
||||||
|
}
|
|
@ -12,6 +12,11 @@ import * as Layout from "./../../utils/layout";
|
||||||
import { LendingInstruction } from "./lending";
|
import { LendingInstruction } from "./lending";
|
||||||
import { LendingReserve } from "./reserve";
|
import { LendingReserve } from "./reserve";
|
||||||
|
|
||||||
|
export enum BorrowAmountType {
|
||||||
|
LiquidityBorrowAmount = 0,
|
||||||
|
CollateralDepositAmount = 1
|
||||||
|
}
|
||||||
|
|
||||||
/// Borrow tokens from a reserve by depositing collateral tokens. The number of borrowed tokens
|
/// Borrow tokens from a reserve by depositing collateral tokens. The number of borrowed tokens
|
||||||
/// is calculated by market price. The debt obligation is tokenized.
|
/// is calculated by market price. The debt obligation is tokenized.
|
||||||
///
|
///
|
||||||
|
@ -33,7 +38,8 @@ import { LendingReserve } from "./reserve";
|
||||||
/// 15 `[]` Rent sysvar
|
/// 15 `[]` Rent sysvar
|
||||||
/// 16 '[]` Token program id
|
/// 16 '[]` Token program id
|
||||||
export const borrowInstruction = (
|
export const borrowInstruction = (
|
||||||
collateralAmount: number | BN,
|
amount: number | BN,
|
||||||
|
amountType: BorrowAmountType,
|
||||||
from: PublicKey, // Collateral input SPL Token account. $authority can transfer $collateralAmount
|
from: PublicKey, // Collateral input SPL Token account. $authority can transfer $collateralAmount
|
||||||
to: PublicKey, // Liquidity output SPL Token account,
|
to: PublicKey, // Liquidity output SPL Token account,
|
||||||
depositReserve: PublicKey,
|
depositReserve: PublicKey,
|
||||||
|
@ -55,17 +61,20 @@ export const borrowInstruction = (
|
||||||
): TransactionInstruction => {
|
): TransactionInstruction => {
|
||||||
const dataLayout = BufferLayout.struct([
|
const dataLayout = BufferLayout.struct([
|
||||||
BufferLayout.u8("instruction"),
|
BufferLayout.u8("instruction"),
|
||||||
Layout.uint64("collateralAmount"),
|
Layout.uint64("amount"),
|
||||||
|
BufferLayout.u8("amountType"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const data = Buffer.alloc(dataLayout.span);
|
const data = Buffer.alloc(dataLayout.span);
|
||||||
dataLayout.encode(
|
dataLayout.encode(
|
||||||
{
|
{
|
||||||
instruction: LendingInstruction.BorrowLiquidity,
|
instruction: LendingInstruction.BorrowLiquidity,
|
||||||
collateralAmount: new BN(collateralAmount),
|
amount: new BN(amount),
|
||||||
|
amountType,
|
||||||
},
|
},
|
||||||
data
|
data
|
||||||
);
|
);
|
||||||
|
debugger;
|
||||||
|
|
||||||
const keys = [
|
const keys = [
|
||||||
{ pubkey: from, isSigner: false, isWritable: true },
|
{ pubkey: from, isSigner: false, isWritable: true },
|
||||||
|
@ -104,9 +113,9 @@ export const borrowInstruction = (
|
||||||
// deposit APY utilization currentUtilizationRate * borrowAPY
|
// deposit APY utilization currentUtilizationRate * borrowAPY
|
||||||
|
|
||||||
export const calculateBorrowAPY = (reserve: LendingReserve) => {
|
export const calculateBorrowAPY = (reserve: LendingReserve) => {
|
||||||
const totalBorrows = reserve.totalBorrowsWad.div(WAD).toNumber();
|
const totalBorrows = reserve.borrowedLiquidityWad.div(WAD).toNumber();
|
||||||
const currentUtilization =
|
const currentUtilization =
|
||||||
totalBorrows / (reserve.totalLiquidity.toNumber() + totalBorrows);
|
totalBorrows / (reserve.availableLiqudity.toNumber() + totalBorrows);
|
||||||
const optimalUtilization = reserve.config.optimalUtilizationRate;
|
const optimalUtilization = reserve.config.optimalUtilizationRate;
|
||||||
let borrowAPY;
|
let borrowAPY;
|
||||||
if (currentUtilization < optimalUtilization) {
|
if (currentUtilization < optimalUtilization) {
|
||||||
|
|
|
@ -64,9 +64,9 @@ export const depositInstruction = (
|
||||||
};
|
};
|
||||||
|
|
||||||
export const calculateDepositAPY = (reserve: LendingReserve) => {
|
export const calculateDepositAPY = (reserve: LendingReserve) => {
|
||||||
const totalBorrows = reserve.totalBorrowsWad.div(WAD).toNumber();
|
const totalBorrows = reserve.borrowedLiquidityWad.div(WAD).toNumber();
|
||||||
const currentUtilization =
|
const currentUtilization =
|
||||||
totalBorrows / (reserve.totalLiquidity.toNumber() + totalBorrows);
|
totalBorrows / (reserve.availableLiqudity.toNumber() + totalBorrows);
|
||||||
|
|
||||||
const borrowAPY = calculateBorrowAPY(reserve);
|
const borrowAPY = calculateBorrowAPY(reserve);
|
||||||
return currentUtilization * borrowAPY;
|
return currentUtilization * borrowAPY;
|
||||||
|
|
|
@ -45,9 +45,9 @@ export const LendingReserveLayout: typeof BufferLayout.Structure = BufferLayout.
|
||||||
),
|
),
|
||||||
|
|
||||||
Layout.uint128("cumulativeBorrowRateWad"),
|
Layout.uint128("cumulativeBorrowRateWad"),
|
||||||
Layout.uint128("totalBorrowsWad"),
|
Layout.uint128("borrowedLiquidityWad"),
|
||||||
|
|
||||||
Layout.uint64("totalLiquidity"),
|
Layout.uint64("availableLiqudity"),
|
||||||
Layout.uint64("collateralMintSupply"),
|
Layout.uint64("collateralMintSupply"),
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
@ -83,9 +83,9 @@ export interface LendingReserve {
|
||||||
// collateralFactor: number;
|
// collateralFactor: number;
|
||||||
|
|
||||||
cumulativeBorrowRateWad: BN;
|
cumulativeBorrowRateWad: BN;
|
||||||
totalBorrowsWad: BN;
|
borrowedLiquidityWad: BN;
|
||||||
|
|
||||||
totalLiquidity: BN;
|
availableLiqudity: BN;
|
||||||
collateralMintSupply: BN;
|
collateralMintSupply: BN;
|
||||||
|
|
||||||
// Layout.uint128("cumulative_borrow_rate"),
|
// Layout.uint128("cumulative_borrow_rate"),
|
||||||
|
|
|
@ -32,6 +32,11 @@ export function Routes() {
|
||||||
<AppLayout>
|
<AppLayout>
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/" component={() => <HomeView />} />
|
<Route exact path="/" component={() => <HomeView />} />
|
||||||
|
<Route
|
||||||
|
exact
|
||||||
|
path="/dashboard/deposits"
|
||||||
|
children={<DashboardView />}
|
||||||
|
/>
|
||||||
<Route
|
<Route
|
||||||
exact
|
exact
|
||||||
path="/dashboard"
|
path="/dashboard"
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
import React from "react";
|
||||||
|
import {
|
||||||
|
useCollateralBalance,
|
||||||
|
useTokenName,
|
||||||
|
useUserBalance,
|
||||||
|
} from "../../hooks";
|
||||||
|
import { LendingReserve } from "../../models/lending";
|
||||||
|
import { TokenIcon } from "../../components/TokenIcon";
|
||||||
|
import { formatNumber } from "../../utils/utils";
|
||||||
|
import { Button, Card } from "antd";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { PublicKey } from "@solana/web3.js";
|
||||||
|
|
||||||
|
export const ReserveItem = (props: {
|
||||||
|
reserve: LendingReserve;
|
||||||
|
address: PublicKey;
|
||||||
|
}) => {
|
||||||
|
const name = useTokenName(props.reserve.liquidityMint);
|
||||||
|
const { balance: tokenBalance } = useUserBalance(props.reserve.liquidityMint);
|
||||||
|
const { balance: collateralBalance } = useCollateralBalance(props.reserve);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link to={`/deposit/${props.address.toBase58()}`}>
|
||||||
|
<Card>
|
||||||
|
<div className="deposit-item">
|
||||||
|
<span style={{ display: "flex" }}>
|
||||||
|
<TokenIcon mintAddress={props.reserve.liquidityMint} />
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
{formatNumber.format(tokenBalance)} {name}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{formatNumber.format(collateralBalance)} {name}
|
||||||
|
</div>
|
||||||
|
<div>--</div>
|
||||||
|
<div>
|
||||||
|
<Button>
|
||||||
|
<span>Deposit</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,32 @@
|
||||||
|
import React from "react";
|
||||||
|
import { LABELS } from "../../constants";
|
||||||
|
import { useUserDeposits, useUserObligations } from "./../../hooks";
|
||||||
|
import { ObligationItem } from "./obligationItem";
|
||||||
|
import "./style.less";
|
||||||
|
|
||||||
|
export const DashboardView = () => {
|
||||||
|
const { userObligations } = useUserObligations();
|
||||||
|
const { userDeposits } = useUserDeposits();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="dashboard-container">
|
||||||
|
<div className="dashboard-left">
|
||||||
|
<span>{LABELS.DASHBOARD_TITLE_DEPOSITS}</span>
|
||||||
|
</div>
|
||||||
|
<div className="dashboard-right">
|
||||||
|
<span>{LABELS.DASHBOARD_TITLE_LOANS}</span>
|
||||||
|
{userObligations.length > 0 && (
|
||||||
|
<div className="dashboard-item dashboard-header">
|
||||||
|
<div>{LABELS.TABLE_TITLE_ASSET}</div>
|
||||||
|
<div>{LABELS.TABLE_TITLE_LOAN_BALANCE}</div>
|
||||||
|
<div>{LABELS.TABLE_TITLE_APY}</div>
|
||||||
|
<div>{LABELS.TABLE_TITLE_ACTION}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{userObligations.map((item) => {
|
||||||
|
return <ObligationItem obligation={item.obligation} />;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,49 @@
|
||||||
|
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 { Button, Card } from "antd";
|
||||||
|
import { Link } from "react-router-dom";
|
||||||
|
import { cache, ParsedAccount, useMint } from "../../contexts/accounts";
|
||||||
|
|
||||||
|
export const ObligationItem = (props: {
|
||||||
|
obligation: ParsedAccount<LendingObligation>;
|
||||||
|
}) => {
|
||||||
|
const { obligation } = props;
|
||||||
|
|
||||||
|
const borrowReserve = cache.get(
|
||||||
|
obligation.info.borrowReserve
|
||||||
|
) as ParsedAccount<LendingReserve>;
|
||||||
|
|
||||||
|
const name = useTokenName(borrowReserve?.info.liquidityMint);
|
||||||
|
|
||||||
|
const liquidityMint = useMint(borrowReserve.info.liquidityMint);
|
||||||
|
|
||||||
|
const borrowAmount = fromLamports(
|
||||||
|
wadToLamports(obligation.info.borrowAmountWad),
|
||||||
|
liquidityMint
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Link to={`/repay/loan/${obligation.pubkey.toBase58()}`}>
|
||||||
|
<Card>
|
||||||
|
<div className="dashboard-item">
|
||||||
|
<span style={{ display: "flex" }}>
|
||||||
|
<TokenIcon mintAddress={borrowReserve?.info.liquidityMint} />
|
||||||
|
{name}
|
||||||
|
</span>
|
||||||
|
<div>
|
||||||
|
{formatNumber.format(borrowAmount)} {name}
|
||||||
|
</div>
|
||||||
|
<div>--</div>
|
||||||
|
<div>
|
||||||
|
<Button>
|
||||||
|
<span>Repay</span>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
};
|
|
@ -0,0 +1,50 @@
|
||||||
|
.dashboard-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
& > div, span {
|
||||||
|
flex: 20%;
|
||||||
|
height: 22px;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > :first-child {
|
||||||
|
flex: 80px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-header {
|
||||||
|
margin: 0px 30px;
|
||||||
|
|
||||||
|
& > div {
|
||||||
|
flex: 20%;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > :first-child {
|
||||||
|
text-align: left;
|
||||||
|
flex: 80px
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-right {
|
||||||
|
flex: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-left {
|
||||||
|
flex: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.dashboard-right, .dashboard-left {
|
||||||
|
flex: 100%;
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,9 +12,8 @@ import {
|
||||||
export const BorrowReserveView = () => {
|
export const BorrowReserveView = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
const lendingReserve = useLendingReserve(id);
|
const lendingReserve = useLendingReserve(id);
|
||||||
const reserve = lendingReserve?.info;
|
|
||||||
|
|
||||||
if (!reserve || !lendingReserve) {
|
if (!lendingReserve) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,13 +22,11 @@ export const BorrowReserveView = () => {
|
||||||
<div className="borrow-reserve-container">
|
<div className="borrow-reserve-container">
|
||||||
<BorrowInput
|
<BorrowInput
|
||||||
className="borrow-reserve-item borrow-reserve-item-left"
|
className="borrow-reserve-item borrow-reserve-item-left"
|
||||||
reserve={reserve}
|
reserve={lendingReserve}
|
||||||
address={lendingReserve.pubkey}
|
|
||||||
/>
|
/>
|
||||||
<SideReserveOverview
|
<SideReserveOverview
|
||||||
className="borrow-reserve-item borrow-reserve-item-right"
|
className="borrow-reserve-item borrow-reserve-item-right"
|
||||||
reserve={reserve}
|
reserve={lendingReserve}
|
||||||
address={lendingReserve.pubkey}
|
|
||||||
mode={SideReserveOverviewMode.Borrow}
|
mode={SideReserveOverviewMode.Borrow}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,33 +10,34 @@ import { formatNumber } from "../../utils/utils";
|
||||||
import { Button, Card } from "antd";
|
import { Button, Card } from "antd";
|
||||||
import { Link } from "react-router-dom";
|
import { Link } from "react-router-dom";
|
||||||
import { PublicKey } from "@solana/web3.js";
|
import { PublicKey } from "@solana/web3.js";
|
||||||
|
import { TokenAccount } from "../../models";
|
||||||
|
import { ParsedAccount } from "../../contexts/accounts";
|
||||||
|
|
||||||
export const ReserveItem = (props: {
|
export const DepositItem = (props: {
|
||||||
reserve: LendingReserve;
|
reserve: ParsedAccount<LendingReserve>;
|
||||||
address: PublicKey;
|
account: TokenAccount;
|
||||||
}) => {
|
}) => {
|
||||||
const name = useTokenName(props.reserve.liquidityMint);
|
const account = props.account.info;
|
||||||
const { balance: tokenBalance } = useUserBalance(props.reserve.liquidityMint);
|
|
||||||
const { balance: collateralBalance } = useCollateralBalance(props.reserve);
|
const mintAddress = props.reserve.info.liquidityMint;
|
||||||
|
const name = useTokenName(mintAddress);
|
||||||
|
const { balance: collateralBalance } = useCollateralBalance(props.reserve.info, props.account.pubkey);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={`/deposit/${props.address.toBase58()}`}>
|
<Link to={`/withdraw/${props.reserve.pubkey.toBase58()}`}>
|
||||||
<Card>
|
<Card>
|
||||||
<div className="deposit-item">
|
<div className="deposit-item">
|
||||||
<span style={{ display: "flex" }}>
|
<span style={{ display: "flex" }}>
|
||||||
<TokenIcon mintAddress={props.reserve.liquidityMint} />
|
<TokenIcon mintAddress={mintAddress} />
|
||||||
{name}
|
{name}
|
||||||
</span>
|
</span>
|
||||||
<div>
|
|
||||||
{formatNumber.format(tokenBalance)} {name}
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
{formatNumber.format(collateralBalance)} {name}
|
{formatNumber.format(collateralBalance)} {name}
|
||||||
</div>
|
</div>
|
||||||
<div>--</div>
|
<div>--</div>
|
||||||
<div>
|
<div>
|
||||||
<Button>
|
<Button>
|
||||||
<span>Deposit</span>
|
<span>Withdraw</span>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,24 +1,37 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { LABELS } from "../../constants";
|
import { LABELS } from "../../constants";
|
||||||
import { useUserObligations } from "./../../hooks";
|
import { useUserDeposits, useUserObligations } from "./../../hooks";
|
||||||
|
import { DepositItem } from "./depositItem";
|
||||||
import { ObligationItem } from "./obligationItem";
|
import { ObligationItem } from "./obligationItem";
|
||||||
import "./style.less";
|
import "./style.less";
|
||||||
|
|
||||||
export const DashboardView = () => {
|
export const DashboardView = () => {
|
||||||
const { userObligations } = useUserObligations();
|
const { userObligations } = useUserObligations();
|
||||||
|
const { userDeposits } = useUserDeposits();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-container">
|
<div className="dashboard-container">
|
||||||
<div>
|
<div className="dashboard-left">
|
||||||
<span>{LABELS.DASHBOARD_TITLE_DEPOSITS}</span>
|
<span>{LABELS.DASHBOARD_TITLE_DEPOSITS}</span>
|
||||||
|
{userDeposits.length > 0 && (
|
||||||
|
<div className="dashboard-item dashboard-header">
|
||||||
|
<div>{LABELS.TABLE_TITLE_DEPOSIT_BALANCE}</div>
|
||||||
|
<div>{LABELS.TABLE_TITLE_LOAN_BALANCE}</div>
|
||||||
|
<div>{LABELS.TABLE_TITLE_APY}</div>
|
||||||
|
<div>{LABELS.TABLE_TITLE_ACTION}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{userDeposits.map(deposit => <DepositItem reserve={deposit.reserve} account={deposit.account} />)
|
||||||
|
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div className="dashboard-right">
|
||||||
<span>{LABELS.DASHBOARD_TITLE_LOANS}</span>
|
<span>{LABELS.DASHBOARD_TITLE_LOANS}</span>
|
||||||
{userObligations.length > 0 && (
|
{userObligations.length > 0 && (
|
||||||
<div className="dashboard-item dashboard-header">
|
<div className="dashboard-item dashboard-header">
|
||||||
<div>{LABELS.TABLE_TITLE_ASSET}</div>
|
<div>{LABELS.TABLE_TITLE_ASSET}</div>
|
||||||
<div>{LABELS.TABLE_TITLE_LOAN_BALANCE}</div>
|
<div>{LABELS.TABLE_TITLE_LOAN_BALANCE}</div>
|
||||||
<div>{LABELS.TABLE_TITLE_APY}</div>
|
<div>{LABELS.TABLE_TITLE_APR}</div>
|
||||||
<div>{LABELS.TABLE_TITLE_ACTION}</div>
|
<div>{LABELS.TABLE_TITLE_ACTION}</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -26,4 +26,25 @@
|
||||||
text-align: left;
|
text-align: left;
|
||||||
flex: 80px
|
flex: 80px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dashboard-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
flex: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-right {
|
||||||
|
flex: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-left {
|
||||||
|
flex: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.dashboard-right, .dashboard-left {
|
||||||
|
flex: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -34,8 +34,7 @@ export const DepositReserveView = () => {
|
||||||
/>
|
/>
|
||||||
<SideReserveOverview
|
<SideReserveOverview
|
||||||
className="deposit-reserve-item deposit-reserve-item-right"
|
className="deposit-reserve-item deposit-reserve-item-right"
|
||||||
reserve={reserve}
|
reserve={lendingReserve}
|
||||||
address={lendingReserve.pubkey}
|
|
||||||
mode={SideReserveOverviewMode.Deposit}
|
mode={SideReserveOverviewMode.Deposit}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
import { LABELS } from "../../constants";
|
||||||
import { useLendingReserves } from "../../hooks";
|
import { useLendingReserves } from "../../hooks";
|
||||||
import { LendingReserveItem } from "./item";
|
import { LendingReserveItem } from "./item";
|
||||||
import "./itemStyle.less";
|
import "./itemStyle.less";
|
||||||
|
@ -11,11 +12,11 @@ export const HomeView = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flexColumn">
|
<div className="flexColumn">
|
||||||
<div className="home-item home-header">
|
<div className="home-item home-header">
|
||||||
<div>Asset</div>
|
<div>{LABELS.TABLE_TITLE_ASSET}</div>
|
||||||
<div>Market Size</div>
|
<div>{LABELS.TABLE_TITLE_MARKET_SIZE}</div>
|
||||||
<div>Total Borrowed</div>
|
<div>{LABELS.TABLE_TITLE_TOTAL_BORROWED}</div>
|
||||||
<div>Deposit APY</div>
|
<div>{LABELS.TABLE_TITLE_DEPOSIT_APR}</div>
|
||||||
<div>Borrow APY</div>
|
<div>{LABELS.TABLE_TITLE_BORROW_APR}</div>
|
||||||
</div>
|
</div>
|
||||||
{reserveAccounts.map((account) => (
|
{reserveAccounts.map((account) => (
|
||||||
<LendingReserveItem reserve={account.info} address={account.pubkey} />
|
<LendingReserveItem reserve={account.info} address={account.pubkey} />
|
||||||
|
|
|
@ -21,14 +21,14 @@ export const LendingReserveItem = (props: {
|
||||||
|
|
||||||
const liquidityMint = useMint(props.reserve.liquidityMint);
|
const liquidityMint = useMint(props.reserve.liquidityMint);
|
||||||
|
|
||||||
const totalLiquidity = fromLamports(
|
const availableLiqudity = fromLamports(
|
||||||
props.reserve.totalLiquidity.toNumber(),
|
props.reserve.availableLiqudity.toNumber(),
|
||||||
liquidityMint
|
liquidityMint
|
||||||
);
|
);
|
||||||
|
|
||||||
const totalBorrows = useMemo(
|
const totalBorrows = useMemo(
|
||||||
() =>
|
() =>
|
||||||
fromLamports(wadToLamports(props.reserve.totalBorrowsWad), liquidityMint),
|
fromLamports(wadToLamports(props.reserve.borrowedLiquidityWad), liquidityMint),
|
||||||
[props.reserve, liquidityMint]
|
[props.reserve, liquidityMint]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ export const LendingReserveItem = (props: {
|
||||||
props.reserve,
|
props.reserve,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const marketSize = totalLiquidity+totalBorrows;
|
const marketSize = availableLiqudity+totalBorrows;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Link to={`/reserve/${props.address.toBase58()}`}>
|
<Link to={`/reserve/${props.address.toBase58()}`}>
|
||||||
|
|
|
@ -38,8 +38,7 @@ export const RepayReserveView = () => {
|
||||||
/>
|
/>
|
||||||
<SideReserveOverview
|
<SideReserveOverview
|
||||||
className="repay-reserve-item repay-reserve-item-right"
|
className="repay-reserve-item repay-reserve-item-right"
|
||||||
reserve={reserve}
|
reserve={lendingReserve}
|
||||||
address={lendingReserve.pubkey}
|
|
||||||
mode={SideReserveOverviewMode.Borrow}
|
mode={SideReserveOverviewMode.Borrow}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -34,8 +34,7 @@ export const WithdrawView = () => {
|
||||||
/>
|
/>
|
||||||
<SideReserveOverview
|
<SideReserveOverview
|
||||||
className="deposit-reserve-item deposit-reserve-item-right"
|
className="deposit-reserve-item deposit-reserve-item-right"
|
||||||
reserve={reserve}
|
reserve={lendingReserve}
|
||||||
address={lendingReserve.pubkey}
|
|
||||||
mode={SideReserveOverviewMode.Deposit}
|
mode={SideReserveOverviewMode.Deposit}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue