feat: add sliders

This commit is contained in:
bartosz-lipinski 2020-12-03 22:27:45 -06:00
parent 2bd278fd41
commit d400f85203
9 changed files with 61 additions and 75 deletions

View File

@ -15,14 +15,9 @@ Any content produced by Solana, or developer resources that Solana provides, are
- [] Facuet add USDC that is using sol airdrop and USDC reserve to give user USDC - [] Facuet add USDC that is using sol airdrop and USDC reserve to give user USDC
- [] Borrow - Convert target ccy to collateral on oposite side - [] Borrow - Convert target ccy to collateral on oposite side
- [] Borrow - liquidity token wrapped SOL should be unwrapped ... - [] Borrow - liquidity token wrapped SOL should be unwrapped ...
- [] Fix slider on repay page - [x] Fix slider on repay page
- [] Add slider to borrow page (100% max collateral) - [x] Add slider to borrow page (100% max collateral)
- [] Add market size on front page - [x] Add market size on front page
- [] Add github link - [] Add github link
- [] Repay from reserve (add selection for obligation/loan) - [] Repay from reserve (add selection for obligation/loan)
- [] Add support for token names in URL in addition to reserve address - [] Add support for token names in URL in addition to reserve address
# TOP for tomorrow
- subscribe to all dex markets that are used by lending reserves
- finish reserve overivew

View File

@ -260,6 +260,10 @@ body {
} }
} }
.ant-slider {
margin: 20px 15px 40px 15px;
}
.token-input { .token-input {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -28,9 +28,6 @@ export const deposit = async (
connection: Connection, connection: Connection,
wallet: any wallet: any
) => { ) => {
// TODO: customize ?
const MAX_UTILIZATION_RATE = 80;
notify({ notify({
message: "Depositing funds...", message: "Depositing funds...",
description: "Please review transactions to approve.", description: "Please review transactions to approve.",
@ -110,6 +107,7 @@ export const deposit = async (
); );
} else { } else {
// TODO: finish reserve init // TODO: finish reserve init
const MAX_UTILIZATION_RATE = 80;
instructions.push( instructions.push(
initReserveInstruction( initReserveInstruction(
amountLamports, amountLamports,

View File

@ -110,21 +110,17 @@ export const repay = async (
) )
); );
try { let tx = await sendTransaction(
let tx = await sendTransaction( connection,
connection, wallet,
wallet, instructions.concat(cleanupInstructions),
instructions.concat(cleanupInstructions), signers,
signers, true
true );
);
notify({ notify({
message: "Funds repaid.", message: "Funds repaid.",
type: "success", type: "success",
description: `Transaction - ${tx}`, description: `Transaction - ${tx}`,
}); });
} catch {
// TODO:
}
}; };

View File

@ -10,7 +10,7 @@ import {
LendingReserveParser, LendingReserveParser,
} from "../../models"; } from "../../models";
import { TokenIcon } from "../TokenIcon"; import { TokenIcon } from "../TokenIcon";
import { Button, Card, Spin } from "antd"; import { Button, Card } from "antd";
import { cache, ParsedAccount } from "../../contexts/accounts"; import { cache, ParsedAccount } from "../../contexts/accounts";
import { NumericInput } from "../Input/numeric"; import { NumericInput } from "../Input/numeric";
import { useConnection } from "../../contexts/connection"; import { useConnection } from "../../contexts/connection";
@ -19,12 +19,9 @@ import { borrow } from "../../actions";
import { CollateralSelector } from "./../CollateralSelector"; import { CollateralSelector } from "./../CollateralSelector";
import "./style.less"; import "./style.less";
import { LABELS } from "../../constants"; import { LABELS } from "../../constants";
import { LoadingOutlined } from "@ant-design/icons";
import { ActionConfirmation } from "./../ActionConfirmation"; import { ActionConfirmation } from "./../ActionConfirmation";
import { BackButton } from "./../BackButton"; import { BackButton } from "./../BackButton";
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
export const BorrowInput = (props: { export const BorrowInput = (props: {
className?: string; className?: string;
reserve: ParsedAccount<LendingReserve>; reserve: ParsedAccount<LendingReserve>;
@ -154,12 +151,10 @@ export const BorrowInput = (props: {
<Button <Button
type="primary" type="primary"
onClick={onBorrow} onClick={onBorrow}
disabled={fromAccounts.length === 0 || pendingTx} loading={pendingTx}
disabled={fromAccounts.length === 0}
> >
{LABELS.BORROW_ACTION} {LABELS.BORROW_ACTION}
{pendingTx && (
<Spin indicator={antIcon} className="action-spinner" />
)}
</Button> </Button>
<BackButton /> <BackButton />
</div> </div>

View File

@ -7,19 +7,16 @@ import {
} from "../../hooks"; } from "../../hooks";
import { LendingReserve } from "../../models/lending"; import { LendingReserve } from "../../models/lending";
import { TokenIcon } from "../TokenIcon"; import { TokenIcon } from "../TokenIcon";
import { Button, Card, Slider, Spin } from "antd"; import { Button, Card, Slider } from "antd";
import { NumericInput } from "../Input/numeric"; import { NumericInput } from "../Input/numeric";
import { useConnection } from "../../contexts/connection"; import { useConnection } from "../../contexts/connection";
import { useWallet } from "../../contexts/wallet"; import { useWallet } from "../../contexts/wallet";
import { deposit } from "../../actions/deposit"; import { deposit } from "../../actions/deposit";
import { PublicKey } from "@solana/web3.js"; import { PublicKey } from "@solana/web3.js";
import "./style.less"; import "./style.less";
import { LoadingOutlined } from "@ant-design/icons";
import { ActionConfirmation } from "./../ActionConfirmation"; import { ActionConfirmation } from "./../ActionConfirmation";
import { LABELS, marks } from "../../constants"; import { LABELS, marks } from "../../constants";
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
export const DepositInput = (props: { export const DepositInput = (props: {
className?: string; className?: string;
reserve: LendingReserve; reserve: LendingReserve;
@ -134,12 +131,10 @@ export const DepositInput = (props: {
<Button <Button
type="primary" type="primary"
onClick={onDeposit} onClick={onDeposit}
disabled={fromAccounts.length === 0 || pendingTx} loading={pendingTx}
disabled={fromAccounts.length === 0}
> >
{LABELS.DEPOSIT_ACTION} {LABELS.DEPOSIT_ACTION}
{pendingTx && (
<Spin indicator={antIcon} className="action-spinner" />
)}
</Button> </Button>
</div> </div>
)} )}

View File

@ -6,7 +6,7 @@ import {
LendingReserveParser, LendingReserveParser,
} from "../../models"; } from "../../models";
import { TokenIcon } from "../TokenIcon"; import { TokenIcon } from "../TokenIcon";
import { Button, Card, Slider, Spin } from "antd"; import { Button, Card, Slider } from "antd";
import { cache, ParsedAccount, useMint } from "../../contexts/accounts"; import { cache, ParsedAccount, useMint } from "../../contexts/accounts";
import { NumericInput } from "../Input/numeric"; import { NumericInput } from "../Input/numeric";
import { useConnection } from "../../contexts/connection"; import { useConnection } from "../../contexts/connection";
@ -15,15 +15,14 @@ import { repay } from "../../actions";
import { CollateralSelector } from "./../CollateralSelector"; import { CollateralSelector } from "./../CollateralSelector";
import "./style.less"; import "./style.less";
import { LABELS, marks } from "../../constants"; import { LABELS, marks } from "../../constants";
import { LoadingOutlined } from "@ant-design/icons";
import { ActionConfirmation } from "./../ActionConfirmation"; import { ActionConfirmation } from "./../ActionConfirmation";
import { fromLamports, wadToLamports } from "../../utils/utils";
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />; import { notify } from "../../utils/notifications";
export const RepayInput = (props: { export const RepayInput = (props: {
className?: string; className?: string;
reserve: ParsedAccount<LendingReserve>; reserve: ParsedAccount<LendingReserve>;
obligation?: ParsedAccount<LendingObligation>; obligation: ParsedAccount<LendingObligation>;
}) => { }) => {
const connection = useConnection(); const connection = useConnection();
const { wallet } = useWallet(); const { wallet } = useWallet();
@ -33,6 +32,14 @@ export const RepayInput = (props: {
const repayReserve = props.reserve; const repayReserve = props.reserve;
const obligation = props.obligation; const obligation = props.obligation;
const liquidityMint = useMint(repayReserve.info.liquidityMint);
const borrowAmountLamports = wadToLamports(obligation.info.borrowAmountWad).toNumber();
const borrowAmount = fromLamports(
borrowAmountLamports,
liquidityMint
);
const [collateralReserveMint, setCollateralReserveMint] = useState<string>(); const [collateralReserveMint, setCollateralReserveMint] = useState<string>();
const collateralReserve = useMemo(() => { const collateralReserve = useMemo(() => {
@ -49,20 +56,17 @@ export const RepayInput = (props: {
repayReserve.info.liquidityMint repayReserve.info.liquidityMint
); );
const repayLiquidityMint = useMint(repayReserve.info.liquidityMint);
// const collateralBalance = useUserBalance(reserve?.collateralMint);
const obligationAccount = useAccountByMint(obligation?.info.tokenMint); const obligationAccount = useAccountByMint(obligation?.info.tokenMint);
const convert = useCallback( const convert = useCallback(
(val: string | number) => { (val: string | number) => {
if (typeof val === "string") { if (typeof val === "string") {
return (parseFloat(val) / balance) * 100; return (parseFloat(val) / borrowAmount) * 100;
} else { } else {
return ((val * balance) / 100).toFixed(2); return ((val * borrowAmount) / 100).toFixed(2);
} }
}, },
[balance] [borrowAmount]
); );
const { value, setValue, mark, setMark, type } = useSliderInput(convert); const { value, setValue, mark, setMark, type } = useSliderInput(convert);
@ -81,11 +85,13 @@ export const RepayInput = (props: {
(async () => { (async () => {
try { try {
const toRepayLamports = type === InputType.Slider
? (mark * borrowAmountLamports) / 100
: Math.ceil(borrowAmountLamports * (parseFloat(value) / borrowAmount));
await repay( await repay(
fromAccounts[0], fromAccounts[0],
type === InputType.Slider toRepayLamports,
? (mark * balanceLamports) / 100
: Math.ceil(balanceLamports * (parseFloat(value) / balance)),
obligation, obligation,
obligationAccount, obligationAccount,
repayReserve, repayReserve,
@ -96,8 +102,13 @@ export const RepayInput = (props: {
setValue(""); setValue("");
setShowConfirmation(true); setShowConfirmation(true);
} catch { } catch (error) {
// TODO: notify({
message: "Unable to repay loan.",
type: "error",
description: error.message,
});
} finally { } finally {
setPendingTx(false); setPendingTx(false);
} }
@ -105,7 +116,8 @@ export const RepayInput = (props: {
}, [ }, [
mark, mark,
value, value,
balance, borrowAmount,
borrowAmountLamports,
balanceLamports, balanceLamports,
type, type,
connection, connection,
@ -171,12 +183,10 @@ export const RepayInput = (props: {
<Button <Button
type="primary" type="primary"
onClick={onRepay} onClick={onRepay}
loading={pendingTx}
disabled={fromAccounts.length === 0} disabled={fromAccounts.length === 0}
> >
{LABELS.REPAY_ACTION} {LABELS.REPAY_ACTION}
{pendingTx && (
<Spin indicator={antIcon} className="action-spinner" />
)}
</Button> </Button>
</div> </div>
)} )}

View File

@ -8,7 +8,7 @@ import {
} from "../../hooks"; } from "../../hooks";
import { LendingReserve } from "../../models/lending"; import { LendingReserve } from "../../models/lending";
import { TokenIcon } from "../TokenIcon"; import { TokenIcon } from "../TokenIcon";
import { Button, Card, Slider, Spin } from "antd"; import { Button, Card, Slider } from "antd";
import { NumericInput } from "../Input/numeric"; import { NumericInput } from "../Input/numeric";
import { useConnection } from "../../contexts/connection"; import { useConnection } from "../../contexts/connection";
import { useWallet } from "../../contexts/wallet"; import { useWallet } from "../../contexts/wallet";
@ -16,11 +16,8 @@ import { withdraw } from "../../actions";
import { PublicKey } from "@solana/web3.js"; import { PublicKey } from "@solana/web3.js";
import "./style.less"; import "./style.less";
import { LABELS, marks } from "../../constants"; import { LABELS, marks } from "../../constants";
import { LoadingOutlined } from "@ant-design/icons";
import { ActionConfirmation } from "./../ActionConfirmation"; import { ActionConfirmation } from "./../ActionConfirmation";
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
export const WithdrawInput = (props: { export const WithdrawInput = (props: {
className?: string; className?: string;
reserve: LendingReserve; reserve: LendingReserve;
@ -140,12 +137,10 @@ export const WithdrawInput = (props: {
<Button <Button
type="primary" type="primary"
onClick={onWithdraw} onClick={onWithdraw}
disabled={fromAccounts.length === 0 || pendingTx} loading={pendingTx}
disabled={fromAccounts.length === 0}
> >
{LABELS.WITHDRAW_ACTION} {LABELS.WITHDRAW_ACTION}
{pendingTx && (
<Spin indicator={antIcon} className="action-spinner" />
)}
</Button> </Button>
</div> </div>
)} )}

View File

@ -22,9 +22,7 @@ export const RepayReserveView = () => {
); );
const reserve = lendingReserve?.info; const reserve = lendingReserve?.info;
console.log([reserveId, obligationId]); if (!reserve || !lendingReserve || !lendingObligation) {
if (!reserve || !lendingReserve) {
return null; return null;
} }