mirror of https://github.com/certusone/oyster.git
Merge pull request #53 from yamijuan/repay-partially
Allow users to liquidate partially
This commit is contained in:
commit
c5db4c6e6e
|
@ -126,8 +126,6 @@ export const borrow = async (
|
||||||
)
|
)
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let amountLamports: number = 0;
|
let amountLamports: number = 0;
|
||||||
let fromLamports: number = 0;
|
let fromLamports: number = 0;
|
||||||
if (amountType === BorrowAmountType.LiquidityBorrowAmount) {
|
if (amountType === BorrowAmountType.LiquidityBorrowAmount) {
|
||||||
|
@ -197,7 +195,6 @@ export const borrow = async (
|
||||||
instructions = [];
|
instructions = [];
|
||||||
cleanupInstructions = [...finalCleanupInstructions];
|
cleanupInstructions = [...finalCleanupInstructions];
|
||||||
|
|
||||||
|
|
||||||
// create approval for transfer transactions
|
// create approval for transfer transactions
|
||||||
const transferAuthority = approve(
|
const transferAuthority = approve(
|
||||||
instructions,
|
instructions,
|
||||||
|
|
|
@ -195,6 +195,7 @@ export const BorrowInput = (props: {
|
||||||
onCollateralReserve={(key) => {
|
onCollateralReserve={(key) => {
|
||||||
setCollateralReserveKey(key);
|
setCollateralReserveKey(key);
|
||||||
}}
|
}}
|
||||||
|
useFirstReserve={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<ArrowDownOutlined />
|
<ArrowDownOutlined />
|
||||||
|
@ -204,7 +205,7 @@ export const BorrowInput = (props: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "space-evenly",
|
justifyContent: "space-evenly",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
marginBottom: 20
|
marginBottom: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CollateralInput
|
<CollateralInput
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
import React, { useEffect, useState } from "react";
|
import React, { useEffect, useState } from "react";
|
||||||
import { cache, ParsedAccount } from "../../contexts/accounts";
|
import { cache, ParsedAccount } from "../../contexts/accounts";
|
||||||
import { useConnectionConfig } from "../../contexts/connection";
|
import { useConnectionConfig } from "../../contexts/connection";
|
||||||
import { useLendingReserves, useUserDeposits } from "../../hooks";
|
import {
|
||||||
|
useLendingReserves,
|
||||||
|
useUserBalance,
|
||||||
|
useUserDeposits,
|
||||||
|
} from "../../hooks";
|
||||||
import {
|
import {
|
||||||
LendingReserve,
|
LendingReserve,
|
||||||
LendingMarket,
|
LendingMarket,
|
||||||
|
@ -27,9 +31,12 @@ export default function CollateralInput(props: {
|
||||||
onLeverage?: (leverage: number) => void;
|
onLeverage?: (leverage: number) => void;
|
||||||
onInputChange: (value: number | null) => void;
|
onInputChange: (value: number | null) => void;
|
||||||
hideBalance?: boolean;
|
hideBalance?: boolean;
|
||||||
|
useWalletBalance?: boolean;
|
||||||
|
useFirstReserve?: boolean;
|
||||||
showLeverageSelector?: boolean;
|
showLeverageSelector?: boolean;
|
||||||
leverage?: number;
|
leverage?: number;
|
||||||
}) {
|
}) {
|
||||||
|
const { balance: tokenBalance } = useUserBalance(props.reserve.liquidityMint);
|
||||||
const { reserveAccounts } = useLendingReserves();
|
const { reserveAccounts } = useLendingReserves();
|
||||||
const { tokenMap } = useConnectionConfig();
|
const { tokenMap } = useConnectionConfig();
|
||||||
const [collateralReserve, setCollateralReserve] = useState<string>();
|
const [collateralReserve, setCollateralReserve] = useState<string>();
|
||||||
|
@ -38,11 +45,15 @@ export default function CollateralInput(props: {
|
||||||
const userDeposits = useUserDeposits();
|
const userDeposits = useUserDeposits();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (props.useWalletBalance) {
|
||||||
|
setBalance(tokenBalance);
|
||||||
|
} else {
|
||||||
const id: string =
|
const id: string =
|
||||||
cache
|
cache
|
||||||
.byParser(LendingReserveParser)
|
.byParser(LendingReserveParser)
|
||||||
.find((acc) => acc === collateralReserve) || "";
|
.find((acc) => acc === collateralReserve) || "";
|
||||||
const parser = cache.get(id) as ParsedAccount<LendingReserve>;
|
const parser = cache.get(id) as ParsedAccount<LendingReserve>;
|
||||||
|
|
||||||
if (parser) {
|
if (parser) {
|
||||||
const collateralDeposit = userDeposits.userDeposits.find(
|
const collateralDeposit = userDeposits.userDeposits.find(
|
||||||
(u) =>
|
(u) =>
|
||||||
|
@ -52,7 +63,8 @@ export default function CollateralInput(props: {
|
||||||
if (collateralDeposit) setBalance(collateralDeposit.info.amount);
|
if (collateralDeposit) setBalance(collateralDeposit.info.amount);
|
||||||
else setBalance(0);
|
else setBalance(0);
|
||||||
}
|
}
|
||||||
}, [collateralReserve, userDeposits]);
|
}
|
||||||
|
}, [collateralReserve, userDeposits, tokenBalance, props.useWalletBalance]);
|
||||||
|
|
||||||
const market = cache.get(props.reserve.lendingMarket) as ParsedAccount<
|
const market = cache.get(props.reserve.lendingMarket) as ParsedAccount<
|
||||||
LendingMarket
|
LendingMarket
|
||||||
|
@ -63,14 +75,23 @@ export default function CollateralInput(props: {
|
||||||
market?.info?.quoteMint
|
market?.info?.quoteMint
|
||||||
);
|
);
|
||||||
|
|
||||||
const renderReserveAccounts = reserveAccounts
|
const filteredReserveAccounts = reserveAccounts
|
||||||
.filter((reserve) => reserve.info !== props.reserve)
|
.filter((reserve) => reserve.info !== props.reserve)
|
||||||
.filter(
|
.filter(
|
||||||
(reserve) =>
|
(reserve) =>
|
||||||
!onlyQuoteAllowed ||
|
!onlyQuoteAllowed ||
|
||||||
reserve.info.liquidityMint.equals(market.info.quoteMint)
|
reserve.info.liquidityMint.equals(market.info.quoteMint)
|
||||||
)
|
);
|
||||||
.map((reserve) => {
|
|
||||||
|
if (
|
||||||
|
!collateralReserve &&
|
||||||
|
props.useFirstReserve &&
|
||||||
|
filteredReserveAccounts.length
|
||||||
|
) {
|
||||||
|
const address = filteredReserveAccounts[0].pubkey.toBase58();
|
||||||
|
setCollateralReserve(address);
|
||||||
|
}
|
||||||
|
const renderReserveAccounts = filteredReserveAccounts.map((reserve) => {
|
||||||
const mint = reserve.info.liquidityMint.toBase58();
|
const mint = reserve.info.liquidityMint.toBase58();
|
||||||
const address = reserve.pubkey.toBase58();
|
const address = reserve.pubkey.toBase58();
|
||||||
const name = getTokenName(tokenMap, mint);
|
const name = getTokenName(tokenMap, mint);
|
||||||
|
|
|
@ -1,35 +1,65 @@
|
||||||
import { Button } from "antd";
|
import { Slider } from "antd";
|
||||||
import Card from "antd/lib/card";
|
import Card from "antd/lib/card";
|
||||||
import React, { useCallback } from "react";
|
import React, { useCallback, useEffect } from "react";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { LABELS } from "../../constants";
|
import { LABELS, marks } from "../../constants";
|
||||||
import { ParsedAccount } from "../../contexts/accounts";
|
import { ParsedAccount, useMint } from "../../contexts/accounts";
|
||||||
import { EnrichedLendingObligation, useUserBalance } from "../../hooks";
|
import {
|
||||||
|
EnrichedLendingObligation,
|
||||||
|
InputType,
|
||||||
|
useSliderInput,
|
||||||
|
useUserBalance,
|
||||||
|
} from "../../hooks";
|
||||||
import { LendingReserve } from "../../models";
|
import { LendingReserve } from "../../models";
|
||||||
import { ActionConfirmation } from "../ActionConfirmation";
|
import { ActionConfirmation } from "../ActionConfirmation";
|
||||||
import { BackButton } from "../BackButton";
|
|
||||||
import { CollateralSelector } from "../CollateralSelector";
|
|
||||||
import { liquidate } from "../../actions";
|
import { liquidate } from "../../actions";
|
||||||
import "./style.less";
|
import "./style.less";
|
||||||
import { useConnection } from "../../contexts/connection";
|
import { useConnection } from "../../contexts/connection";
|
||||||
import { useWallet } from "../../contexts/wallet";
|
import { useWallet } from "../../contexts/wallet";
|
||||||
import { wadToLamports } from "../../utils/utils";
|
import { fromLamports, wadToLamports } from "../../utils/utils";
|
||||||
|
import CollateralInput from "../CollateralInput";
|
||||||
|
import { notify } from "../../utils/notifications";
|
||||||
|
import { ConnectButton } from "../ConnectButton";
|
||||||
|
import { useMidPriceInUSD } from "../../contexts/market";
|
||||||
|
|
||||||
export const LiquidateInput = (props: {
|
export const LiquidateInput = (props: {
|
||||||
className?: string;
|
className?: string;
|
||||||
repayReserve: ParsedAccount<LendingReserve>;
|
repayReserve: ParsedAccount<LendingReserve>;
|
||||||
withdrawReserve?: ParsedAccount<LendingReserve>;
|
withdrawReserve: ParsedAccount<LendingReserve>;
|
||||||
obligation: EnrichedLendingObligation;
|
obligation: EnrichedLendingObligation;
|
||||||
}) => {
|
}) => {
|
||||||
const connection = useConnection();
|
const connection = useConnection();
|
||||||
const { wallet } = useWallet();
|
const { wallet } = useWallet();
|
||||||
const { repayReserve, withdrawReserve, obligation } = props;
|
const { repayReserve, withdrawReserve, obligation } = props;
|
||||||
|
const [lastTyped, setLastTyped] = useState("liquidate");
|
||||||
const [pendingTx, setPendingTx] = useState(false);
|
const [pendingTx, setPendingTx] = useState(false);
|
||||||
const [showConfirmation, setShowConfirmation] = useState(false);
|
const [showConfirmation, setShowConfirmation] = useState(false);
|
||||||
|
const [collateralValue, setCollateralValue] = useState("");
|
||||||
|
|
||||||
const { accounts: fromAccounts } = useUserBalance(
|
const liquidityMint = useMint(repayReserve.info.liquidityMint);
|
||||||
|
const { accounts: fromAccounts, balance: tokenBalance } = useUserBalance(
|
||||||
repayReserve?.info.liquidityMint
|
repayReserve?.info.liquidityMint
|
||||||
);
|
);
|
||||||
|
const borrowAmountLamports = wadToLamports(
|
||||||
|
obligation.info.borrowAmountWad
|
||||||
|
).toNumber();
|
||||||
|
|
||||||
|
const borrowAmount = fromLamports(borrowAmountLamports, liquidityMint);
|
||||||
|
|
||||||
|
const convert = useCallback(
|
||||||
|
(val: string | number) => {
|
||||||
|
const minAmount = Math.min(tokenBalance || Infinity, borrowAmount);
|
||||||
|
setLastTyped("liquidate");
|
||||||
|
if (typeof val === "string") {
|
||||||
|
return (parseFloat(val) / minAmount) * 100;
|
||||||
|
} else {
|
||||||
|
return (val * minAmount) / 100;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[borrowAmount, tokenBalance]
|
||||||
|
);
|
||||||
|
|
||||||
|
const { value, setValue, pct, setPct, type } = useSliderInput(convert);
|
||||||
|
|
||||||
const onLiquidate = useCallback(() => {
|
const onLiquidate = useCallback(() => {
|
||||||
if (!withdrawReserve) {
|
if (!withdrawReserve) {
|
||||||
|
@ -40,20 +70,33 @@ export const LiquidateInput = (props: {
|
||||||
|
|
||||||
(async () => {
|
(async () => {
|
||||||
try {
|
try {
|
||||||
|
const toLiquidateLamports =
|
||||||
|
type === InputType.Percent && tokenBalance >= borrowAmount
|
||||||
|
? (pct * borrowAmountLamports) / 100
|
||||||
|
: Math.ceil(
|
||||||
|
borrowAmountLamports * (parseFloat(value) / borrowAmount)
|
||||||
|
);
|
||||||
await liquidate(
|
await liquidate(
|
||||||
connection,
|
connection,
|
||||||
wallet,
|
wallet,
|
||||||
fromAccounts[0],
|
fromAccounts[0],
|
||||||
// TODO: ensure user has available amount
|
// TODO: ensure user has available amount
|
||||||
wadToLamports(obligation.info.borrowAmountWad).toNumber(),
|
toLiquidateLamports,
|
||||||
obligation.account,
|
obligation.account,
|
||||||
repayReserve,
|
repayReserve,
|
||||||
withdrawReserve
|
withdrawReserve
|
||||||
);
|
);
|
||||||
|
|
||||||
|
setValue("");
|
||||||
|
setCollateralValue("");
|
||||||
setShowConfirmation(true);
|
setShowConfirmation(true);
|
||||||
} catch {
|
} catch (error) {
|
||||||
// TODO:
|
// TODO:
|
||||||
|
notify({
|
||||||
|
message: "Unable to liquidate loan.",
|
||||||
|
type: "error",
|
||||||
|
description: error.message,
|
||||||
|
});
|
||||||
} finally {
|
} finally {
|
||||||
setPendingTx(false);
|
setPendingTx(false);
|
||||||
}
|
}
|
||||||
|
@ -65,8 +108,64 @@ export const LiquidateInput = (props: {
|
||||||
repayReserve,
|
repayReserve,
|
||||||
wallet,
|
wallet,
|
||||||
connection,
|
connection,
|
||||||
|
value,
|
||||||
|
setValue,
|
||||||
|
borrowAmount,
|
||||||
|
borrowAmountLamports,
|
||||||
|
pct,
|
||||||
|
tokenBalance,
|
||||||
|
type,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const collateralPrice = useMidPriceInUSD(
|
||||||
|
withdrawReserve?.info.liquidityMint.toBase58()
|
||||||
|
)?.price;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (withdrawReserve && lastTyped === "liquidate") {
|
||||||
|
const collateralInQuote = obligation.info.collateralInQuote;
|
||||||
|
const collateral = collateralInQuote / collateralPrice;
|
||||||
|
if (value) {
|
||||||
|
const borrowRatio = (parseFloat(value) / borrowAmount) * 100;
|
||||||
|
const collateralAmount = (borrowRatio * collateral) / 100;
|
||||||
|
setCollateralValue(collateralAmount.toString());
|
||||||
|
} else {
|
||||||
|
setCollateralValue("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
borrowAmount,
|
||||||
|
collateralPrice,
|
||||||
|
withdrawReserve,
|
||||||
|
lastTyped,
|
||||||
|
obligation.info.collateralInQuote,
|
||||||
|
value,
|
||||||
|
]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (withdrawReserve && lastTyped === "collateral") {
|
||||||
|
const collateralInQuote = obligation.info.collateralInQuote;
|
||||||
|
const collateral = collateralInQuote / collateralPrice;
|
||||||
|
if (collateralValue) {
|
||||||
|
const collateralRatio =
|
||||||
|
(parseFloat(collateralValue) / collateral) * 100;
|
||||||
|
const borrowValue = (collateralRatio * borrowAmount) / 100;
|
||||||
|
setValue(borrowValue.toString());
|
||||||
|
} else {
|
||||||
|
setValue("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [
|
||||||
|
borrowAmount,
|
||||||
|
collateralPrice,
|
||||||
|
withdrawReserve,
|
||||||
|
collateralValue,
|
||||||
|
lastTyped,
|
||||||
|
obligation.info.collateralInQuote,
|
||||||
|
setValue,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (!withdrawReserve) return null;
|
||||||
const bodyStyle: React.CSSProperties = {
|
const bodyStyle: React.CSSProperties = {
|
||||||
display: "flex",
|
display: "flex",
|
||||||
flex: 1,
|
flex: 1,
|
||||||
|
@ -87,23 +186,58 @@ export const LiquidateInput = (props: {
|
||||||
justifyContent: "space-around",
|
justifyContent: "space-around",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="liquidate-input-title">
|
<div className="repay-input-title">{LABELS.LIQUIDATE_QUESTION}</div>
|
||||||
{LABELS.SELECT_COLLATERAL}
|
<div
|
||||||
</div>
|
style={{
|
||||||
<CollateralSelector
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-evenly",
|
||||||
|
alignItems: "center",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CollateralInput
|
||||||
|
title="Liquidate Amount"
|
||||||
reserve={repayReserve.info}
|
reserve={repayReserve.info}
|
||||||
collateralReserve={withdrawReserve?.pubkey.toBase58()}
|
amount={parseFloat(value) || 0}
|
||||||
|
onInputChange={(val: number | null) => {
|
||||||
|
setValue(val?.toString() || "");
|
||||||
|
setLastTyped("liquidate");
|
||||||
|
}}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
|
useWalletBalance={true}
|
||||||
/>
|
/>
|
||||||
<Button
|
</div>
|
||||||
|
<Slider marks={marks} value={pct} onChange={setPct} />
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
display: "flex",
|
||||||
|
flexDirection: "row",
|
||||||
|
justifyContent: "space-evenly",
|
||||||
|
alignItems: "center",
|
||||||
|
marginBottom: 20,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CollateralInput
|
||||||
|
title="Collateral Amount (estimated)"
|
||||||
|
reserve={withdrawReserve?.info}
|
||||||
|
amount={parseFloat(collateralValue) || 0}
|
||||||
|
onInputChange={(val: number | null) => {
|
||||||
|
setCollateralValue(val?.toString() || "");
|
||||||
|
setLastTyped("collateral");
|
||||||
|
}}
|
||||||
|
disabled={true}
|
||||||
|
hideBalance={true}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<ConnectButton
|
||||||
type="primary"
|
type="primary"
|
||||||
|
size="large"
|
||||||
onClick={onLiquidate}
|
onClick={onLiquidate}
|
||||||
disabled={fromAccounts.length === 0}
|
|
||||||
loading={pendingTx}
|
loading={pendingTx}
|
||||||
|
disabled={fromAccounts.length === 0}
|
||||||
>
|
>
|
||||||
{LABELS.LIQUIDATE_ACTION}
|
{LABELS.LIQUIDATE_ACTION}
|
||||||
</Button>
|
</ConnectButton>
|
||||||
<BackButton />
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</Card>
|
</Card>
|
||||||
|
|
|
@ -70,7 +70,7 @@ export const LoanInfoLine = (props: {
|
||||||
<Card className={props.className}>
|
<Card className={props.className}>
|
||||||
<Statistic
|
<Statistic
|
||||||
title="Collateral"
|
title="Collateral"
|
||||||
value={obligation.info.borrowedInQuote}
|
value={obligation.info.collateralInQuote}
|
||||||
formatter={(val) => (
|
formatter={(val) => (
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
|
|
@ -38,6 +38,9 @@ export const RepayInput = (props: {
|
||||||
const obligation = props.obligation;
|
const obligation = props.obligation;
|
||||||
|
|
||||||
const liquidityMint = useMint(repayReserve.info.liquidityMint);
|
const liquidityMint = useMint(repayReserve.info.liquidityMint);
|
||||||
|
const { balance: tokenBalance } = useUserBalance(
|
||||||
|
repayReserve.info.liquidityMint
|
||||||
|
);
|
||||||
|
|
||||||
const borrowAmountLamports = wadToLamports(
|
const borrowAmountLamports = wadToLamports(
|
||||||
obligation.info.borrowAmountWad
|
obligation.info.borrowAmountWad
|
||||||
|
@ -53,14 +56,15 @@ export const RepayInput = (props: {
|
||||||
|
|
||||||
const convert = useCallback(
|
const convert = useCallback(
|
||||||
(val: string | number) => {
|
(val: string | number) => {
|
||||||
|
const minAmount = Math.min(tokenBalance || Infinity, borrowAmount);
|
||||||
setLastTyped("repay");
|
setLastTyped("repay");
|
||||||
if (typeof val === "string") {
|
if (typeof val === "string") {
|
||||||
return (parseFloat(val) / borrowAmount) * 100;
|
return (parseFloat(val) / minAmount) * 100;
|
||||||
} else {
|
} else {
|
||||||
return (val * borrowAmount) / 100;
|
return (val * minAmount) / 100;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[borrowAmount]
|
[borrowAmount, tokenBalance]
|
||||||
);
|
);
|
||||||
|
|
||||||
const { value, setValue, pct, setPct, type } = useSliderInput(convert);
|
const { value, setValue, pct, setPct, type } = useSliderInput(convert);
|
||||||
|
@ -211,7 +215,7 @@ export const RepayInput = (props: {
|
||||||
setLastTyped("repay");
|
setLastTyped("repay");
|
||||||
}}
|
}}
|
||||||
disabled={true}
|
disabled={true}
|
||||||
hideBalance={true}
|
useWalletBalance={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<Slider marks={marks} value={pct} onChange={setPct} />
|
<Slider marks={marks} value={pct} onChange={setPct} />
|
||||||
|
@ -221,7 +225,7 @@ export const RepayInput = (props: {
|
||||||
flexDirection: "row",
|
flexDirection: "row",
|
||||||
justifyContent: "space-evenly",
|
justifyContent: "space-evenly",
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
marginBottom: 20
|
marginBottom: 20,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CollateralInput
|
<CollateralInput
|
||||||
|
|
|
@ -40,6 +40,7 @@ export const LABELS = {
|
||||||
NO_COLLATERAL: "No collateral",
|
NO_COLLATERAL: "No collateral",
|
||||||
NO_DEPOSITS: "No deposits",
|
NO_DEPOSITS: "No deposits",
|
||||||
NO_LOANS: "No loans",
|
NO_LOANS: "No loans",
|
||||||
|
LIQUIDATE_QUESTION: "How much would you like to liquidate?",
|
||||||
LIQUIDATE_ACTION: "Liquidate",
|
LIQUIDATE_ACTION: "Liquidate",
|
||||||
LIQUIDATE_NO_LOANS: "There are no loans to liquidate.",
|
LIQUIDATE_NO_LOANS: "There are no loans to liquidate.",
|
||||||
TABLE_TITLE_ASSET: "Asset",
|
TABLE_TITLE_ASSET: "Asset",
|
||||||
|
|
|
@ -18,7 +18,11 @@ export const BorrowView = () => {
|
||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
{reserveAccounts.map((account) => (
|
{reserveAccounts.map((account) => (
|
||||||
<BorrowItem key={account.pubkey.toBase58()} reserve={account.info} address={account.pubkey} />
|
<BorrowItem
|
||||||
|
key={account.pubkey.toBase58()}
|
||||||
|
reserve={account.info}
|
||||||
|
address={account.pubkey}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -33,7 +33,10 @@ export const DashboardDeposits = () => {
|
||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
{userDeposits.map((deposit) => (
|
{userDeposits.map((deposit) => (
|
||||||
<DepositItem key={deposit.account.pubkey.toBase58()} userDeposit={deposit} />
|
<DepositItem
|
||||||
|
key={deposit.account.pubkey.toBase58()}
|
||||||
|
userDeposit={deposit}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -23,9 +23,7 @@ export const DashboardView = () => {
|
||||||
/>
|
/>
|
||||||
{LABELS.DASHBOARD_INFO}
|
{LABELS.DASHBOARD_INFO}
|
||||||
</div>
|
</div>
|
||||||
):
|
) : userDeposits.length === 0 && userObligations.length === 0 ? (
|
||||||
userDeposits.length === 0 && userObligations.length === 0 ?
|
|
||||||
(
|
|
||||||
<div className="dashboard-info">
|
<div className="dashboard-info">
|
||||||
<img
|
<img
|
||||||
src="splash.svg"
|
src="splash.svg"
|
||||||
|
@ -37,14 +35,18 @@ export const DashboardView = () => {
|
||||||
) : (
|
) : (
|
||||||
<Row gutter={GUTTER}>
|
<Row gutter={GUTTER}>
|
||||||
<Col md={24} xl={12} span={24}>
|
<Col md={24} xl={12} span={24}>
|
||||||
{userDeposits.length > 0 ?
|
{userDeposits.length > 0 ? (
|
||||||
<DashboardDeposits /> :
|
<DashboardDeposits />
|
||||||
<Card>{LABELS.NO_DEPOSITS}</Card> }
|
) : (
|
||||||
|
<Card>{LABELS.NO_DEPOSITS}</Card>
|
||||||
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
<Col md={24} xl={12} span={24}>
|
<Col md={24} xl={12} span={24}>
|
||||||
{userObligations.length > 0 ?
|
{userObligations.length > 0 ? (
|
||||||
<DashboardObligations /> :
|
<DashboardObligations />
|
||||||
<Card>{LABELS.NO_LOANS}</Card> }
|
) : (
|
||||||
|
<Card>{LABELS.NO_LOANS}</Card>
|
||||||
|
)}
|
||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
)}
|
)}
|
||||||
|
|
|
@ -35,9 +35,12 @@ export const DashboardObligations = () => {
|
||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
{userObligations.map((item) => {
|
{userObligations.map((item) => {
|
||||||
return <ObligationItem
|
return (
|
||||||
|
<ObligationItem
|
||||||
key={item.obligation.account.pubkey.toBase58()}
|
key={item.obligation.account.pubkey.toBase58()}
|
||||||
obligation={item.obligation} />;
|
obligation={item.obligation}
|
||||||
|
/>
|
||||||
|
);
|
||||||
})}
|
})}
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
|
|
|
@ -17,7 +17,11 @@ export const DepositView = () => {
|
||||||
<div></div>
|
<div></div>
|
||||||
</div>
|
</div>
|
||||||
{reserveAccounts.map((account) => (
|
{reserveAccounts.map((account) => (
|
||||||
<ReserveItem key={account.pubkey.toBase58()} reserve={account.info} address={account.pubkey} />
|
<ReserveItem
|
||||||
|
key={account.pubkey.toBase58()}
|
||||||
|
reserve={account.info}
|
||||||
|
address={account.pubkey}
|
||||||
|
/>
|
||||||
))}
|
))}
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -13,7 +13,6 @@ import { LiquidateInput } from "../../components/LiquidateInput";
|
||||||
import "./style.less";
|
import "./style.less";
|
||||||
import { Col, Row } from "antd";
|
import { Col, Row } from "antd";
|
||||||
import { GUTTER } from "../../constants";
|
import { GUTTER } from "../../constants";
|
||||||
import { BorrowInput } from "../../components/BorrowInput";
|
|
||||||
|
|
||||||
export const LiquidateReserveView = () => {
|
export const LiquidateReserveView = () => {
|
||||||
const { id } = useParams<{ id: string }>();
|
const { id } = useParams<{ id: string }>();
|
||||||
|
|
Loading…
Reference in New Issue