mirror of https://github.com/certusone/oyster.git
feat: add sliders
This commit is contained in:
parent
2bd278fd41
commit
d400f85203
11
README.md
11
README.md
|
@ -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
|
||||
- [] Borrow - Convert target ccy to collateral on oposite side
|
||||
- [] Borrow - liquidity token wrapped SOL should be unwrapped ...
|
||||
- [] Fix slider on repay page
|
||||
- [] Add slider to borrow page (100% max collateral)
|
||||
- [] Add market size on front page
|
||||
- [x] Fix slider on repay page
|
||||
- [x] Add slider to borrow page (100% max collateral)
|
||||
- [x] Add market size on front page
|
||||
- [] Add github link
|
||||
- [] Repay from reserve (add selection for obligation/loan)
|
||||
- [] 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
|
||||
|
|
|
@ -260,6 +260,10 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.ant-slider {
|
||||
margin: 20px 15px 40px 15px;
|
||||
}
|
||||
|
||||
.token-input {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
@ -28,9 +28,6 @@ export const deposit = async (
|
|||
connection: Connection,
|
||||
wallet: any
|
||||
) => {
|
||||
// TODO: customize ?
|
||||
const MAX_UTILIZATION_RATE = 80;
|
||||
|
||||
notify({
|
||||
message: "Depositing funds...",
|
||||
description: "Please review transactions to approve.",
|
||||
|
@ -110,6 +107,7 @@ export const deposit = async (
|
|||
);
|
||||
} else {
|
||||
// TODO: finish reserve init
|
||||
const MAX_UTILIZATION_RATE = 80;
|
||||
instructions.push(
|
||||
initReserveInstruction(
|
||||
amountLamports,
|
||||
|
|
|
@ -110,7 +110,6 @@ export const repay = async (
|
|||
)
|
||||
);
|
||||
|
||||
try {
|
||||
let tx = await sendTransaction(
|
||||
connection,
|
||||
wallet,
|
||||
|
@ -124,7 +123,4 @@ export const repay = async (
|
|||
type: "success",
|
||||
description: `Transaction - ${tx}`,
|
||||
});
|
||||
} catch {
|
||||
// TODO:
|
||||
}
|
||||
};
|
||||
|
|
|
@ -10,7 +10,7 @@ import {
|
|||
LendingReserveParser,
|
||||
} from "../../models";
|
||||
import { TokenIcon } from "../TokenIcon";
|
||||
import { Button, Card, Spin } from "antd";
|
||||
import { Button, Card } from "antd";
|
||||
import { cache, ParsedAccount } from "../../contexts/accounts";
|
||||
import { NumericInput } from "../Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
|
@ -19,12 +19,9 @@ import { borrow } from "../../actions";
|
|||
import { CollateralSelector } from "./../CollateralSelector";
|
||||
import "./style.less";
|
||||
import { LABELS } from "../../constants";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import { ActionConfirmation } from "./../ActionConfirmation";
|
||||
import { BackButton } from "./../BackButton";
|
||||
|
||||
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
|
||||
|
||||
export const BorrowInput = (props: {
|
||||
className?: string;
|
||||
reserve: ParsedAccount<LendingReserve>;
|
||||
|
@ -154,12 +151,10 @@ export const BorrowInput = (props: {
|
|||
<Button
|
||||
type="primary"
|
||||
onClick={onBorrow}
|
||||
disabled={fromAccounts.length === 0 || pendingTx}
|
||||
loading={pendingTx}
|
||||
disabled={fromAccounts.length === 0}
|
||||
>
|
||||
{LABELS.BORROW_ACTION}
|
||||
{pendingTx && (
|
||||
<Spin indicator={antIcon} className="action-spinner" />
|
||||
)}
|
||||
</Button>
|
||||
<BackButton />
|
||||
</div>
|
||||
|
|
|
@ -7,19 +7,16 @@ import {
|
|||
} from "../../hooks";
|
||||
import { LendingReserve } from "../../models/lending";
|
||||
import { TokenIcon } from "../TokenIcon";
|
||||
import { Button, Card, Slider, Spin } from "antd";
|
||||
import { Button, Card, Slider } from "antd";
|
||||
import { NumericInput } from "../Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
import { deposit } from "../../actions/deposit";
|
||||
import { PublicKey } from "@solana/web3.js";
|
||||
import "./style.less";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import { ActionConfirmation } from "./../ActionConfirmation";
|
||||
import { LABELS, marks } from "../../constants";
|
||||
|
||||
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
|
||||
|
||||
export const DepositInput = (props: {
|
||||
className?: string;
|
||||
reserve: LendingReserve;
|
||||
|
@ -134,12 +131,10 @@ export const DepositInput = (props: {
|
|||
<Button
|
||||
type="primary"
|
||||
onClick={onDeposit}
|
||||
disabled={fromAccounts.length === 0 || pendingTx}
|
||||
loading={pendingTx}
|
||||
disabled={fromAccounts.length === 0}
|
||||
>
|
||||
{LABELS.DEPOSIT_ACTION}
|
||||
{pendingTx && (
|
||||
<Spin indicator={antIcon} className="action-spinner" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -6,7 +6,7 @@ import {
|
|||
LendingReserveParser,
|
||||
} from "../../models";
|
||||
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 { NumericInput } from "../Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
|
@ -15,15 +15,14 @@ import { repay } from "../../actions";
|
|||
import { CollateralSelector } from "./../CollateralSelector";
|
||||
import "./style.less";
|
||||
import { LABELS, marks } from "../../constants";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import { ActionConfirmation } from "./../ActionConfirmation";
|
||||
|
||||
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
|
||||
import { fromLamports, wadToLamports } from "../../utils/utils";
|
||||
import { notify } from "../../utils/notifications";
|
||||
|
||||
export const RepayInput = (props: {
|
||||
className?: string;
|
||||
reserve: ParsedAccount<LendingReserve>;
|
||||
obligation?: ParsedAccount<LendingObligation>;
|
||||
obligation: ParsedAccount<LendingObligation>;
|
||||
}) => {
|
||||
const connection = useConnection();
|
||||
const { wallet } = useWallet();
|
||||
|
@ -33,6 +32,14 @@ export const RepayInput = (props: {
|
|||
const repayReserve = props.reserve;
|
||||
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 collateralReserve = useMemo(() => {
|
||||
|
@ -49,20 +56,17 @@ export const RepayInput = (props: {
|
|||
repayReserve.info.liquidityMint
|
||||
);
|
||||
|
||||
const repayLiquidityMint = useMint(repayReserve.info.liquidityMint);
|
||||
// const collateralBalance = useUserBalance(reserve?.collateralMint);
|
||||
|
||||
const obligationAccount = useAccountByMint(obligation?.info.tokenMint);
|
||||
|
||||
const convert = useCallback(
|
||||
(val: string | number) => {
|
||||
if (typeof val === "string") {
|
||||
return (parseFloat(val) / balance) * 100;
|
||||
return (parseFloat(val) / borrowAmount) * 100;
|
||||
} else {
|
||||
return ((val * balance) / 100).toFixed(2);
|
||||
return ((val * borrowAmount) / 100).toFixed(2);
|
||||
}
|
||||
},
|
||||
[balance]
|
||||
[borrowAmount]
|
||||
);
|
||||
|
||||
const { value, setValue, mark, setMark, type } = useSliderInput(convert);
|
||||
|
@ -81,11 +85,13 @@ export const RepayInput = (props: {
|
|||
|
||||
(async () => {
|
||||
try {
|
||||
const toRepayLamports = type === InputType.Slider
|
||||
? (mark * borrowAmountLamports) / 100
|
||||
: Math.ceil(borrowAmountLamports * (parseFloat(value) / borrowAmount));
|
||||
|
||||
await repay(
|
||||
fromAccounts[0],
|
||||
type === InputType.Slider
|
||||
? (mark * balanceLamports) / 100
|
||||
: Math.ceil(balanceLamports * (parseFloat(value) / balance)),
|
||||
toRepayLamports,
|
||||
obligation,
|
||||
obligationAccount,
|
||||
repayReserve,
|
||||
|
@ -96,8 +102,13 @@ export const RepayInput = (props: {
|
|||
|
||||
setValue("");
|
||||
setShowConfirmation(true);
|
||||
} catch {
|
||||
// TODO:
|
||||
} catch (error) {
|
||||
notify({
|
||||
message: "Unable to repay loan.",
|
||||
type: "error",
|
||||
description: error.message,
|
||||
});
|
||||
|
||||
} finally {
|
||||
setPendingTx(false);
|
||||
}
|
||||
|
@ -105,7 +116,8 @@ export const RepayInput = (props: {
|
|||
}, [
|
||||
mark,
|
||||
value,
|
||||
balance,
|
||||
borrowAmount,
|
||||
borrowAmountLamports,
|
||||
balanceLamports,
|
||||
type,
|
||||
connection,
|
||||
|
@ -171,12 +183,10 @@ export const RepayInput = (props: {
|
|||
<Button
|
||||
type="primary"
|
||||
onClick={onRepay}
|
||||
loading={pendingTx}
|
||||
disabled={fromAccounts.length === 0}
|
||||
>
|
||||
{LABELS.REPAY_ACTION}
|
||||
{pendingTx && (
|
||||
<Spin indicator={antIcon} className="action-spinner" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
} from "../../hooks";
|
||||
import { LendingReserve } from "../../models/lending";
|
||||
import { TokenIcon } from "../TokenIcon";
|
||||
import { Button, Card, Slider, Spin } from "antd";
|
||||
import { Button, Card, Slider } from "antd";
|
||||
import { NumericInput } from "../Input/numeric";
|
||||
import { useConnection } from "../../contexts/connection";
|
||||
import { useWallet } from "../../contexts/wallet";
|
||||
|
@ -16,11 +16,8 @@ import { withdraw } from "../../actions";
|
|||
import { PublicKey } from "@solana/web3.js";
|
||||
import "./style.less";
|
||||
import { LABELS, marks } from "../../constants";
|
||||
import { LoadingOutlined } from "@ant-design/icons";
|
||||
import { ActionConfirmation } from "./../ActionConfirmation";
|
||||
|
||||
const antIcon = <LoadingOutlined style={{ fontSize: 24 }} spin />;
|
||||
|
||||
export const WithdrawInput = (props: {
|
||||
className?: string;
|
||||
reserve: LendingReserve;
|
||||
|
@ -140,12 +137,10 @@ export const WithdrawInput = (props: {
|
|||
<Button
|
||||
type="primary"
|
||||
onClick={onWithdraw}
|
||||
disabled={fromAccounts.length === 0 || pendingTx}
|
||||
loading={pendingTx}
|
||||
disabled={fromAccounts.length === 0}
|
||||
>
|
||||
{LABELS.WITHDRAW_ACTION}
|
||||
{pendingTx && (
|
||||
<Spin indicator={antIcon} className="action-spinner" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
|
|
|
@ -22,9 +22,7 @@ export const RepayReserveView = () => {
|
|||
);
|
||||
const reserve = lendingReserve?.info;
|
||||
|
||||
console.log([reserveId, obligationId]);
|
||||
|
||||
if (!reserve || !lendingReserve) {
|
||||
if (!reserve || !lendingReserve || !lendingObligation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue