From 31020e7e86750b4c0f6346f69465c54d7b07276c Mon Sep 17 00:00:00 2001 From: bartosz-lipinski <264380+bartosz-lipinski@users.noreply.github.com> Date: Tue, 24 Nov 2020 14:05:38 -0600 Subject: [PATCH] feat: repay --- README.md | 1 + src/actions/repay.tsx | 4 +- src/components/AppBar/index.tsx | 7 +-- src/components/BorrowInput/index.tsx | 7 +-- src/components/ConnectButton/index.tsx | 13 +++++ src/components/Layout/index.tsx | 15 +++--- src/components/RepayInput/index.tsx | 17 +++--- src/components/ReserveStatus/index.tsx | 3 +- src/components/SideReserveOverview/index.tsx | 2 +- src/components/UserLendingCard/index.tsx | 10 ++-- src/components/WithdrawInput/index.tsx | 5 +- src/constants/index.tsx | 3 ++ src/constants/labels.ts | 30 +++++++++++ src/constants/math.ts | 6 +++ src/hooks/index.ts | 1 + src/hooks/useBorrowedAmount.ts | 53 +++++++++++++++++++ src/hooks/useLendingReserves.ts | 4 +- src/hooks/useUserObligationByReserve.ts | 13 ++--- src/hooks/useUserObligations.ts | 2 +- src/models/lending/obligation.ts | 8 +-- src/models/lending/reserve.ts | 44 ++++++++++++--- src/routes.tsx | 2 +- src/utils/utils.ts | 6 +-- src/views/dashboard/depositItem.tsx | 46 ++++++++++++++++ src/views/dashboard/index.tsx | 21 +++++--- src/views/dashboard/obligationItem.tsx | 8 +-- .../dashboard/{itemStyle.less => style.less} | 4 +- src/views/faucet/index.tsx | 15 +++--- src/views/home/item.tsx | 13 +++-- src/views/repayReserve/index.tsx | 5 +- 30 files changed, 287 insertions(+), 81 deletions(-) create mode 100644 src/components/ConnectButton/index.tsx create mode 100644 src/constants/index.tsx create mode 100644 src/constants/labels.ts create mode 100644 src/constants/math.ts create mode 100644 src/hooks/useBorrowedAmount.ts create mode 100644 src/views/dashboard/depositItem.tsx rename src/views/dashboard/{itemStyle.less => style.less} (89%) diff --git a/README.md b/README.md index c1ba5fb..c82b9c5 100644 --- a/README.md +++ b/README.md @@ -19,4 +19,5 @@ Any content produced by Solana, or developer resources that Solana provides, are - [] Add slider to borrow page (100% max collateral) - [] Add market size on front page - [] Add github link +- [] Repay from reserve (add selection for obligation/loan) - [] \ No newline at end of file diff --git a/src/actions/repay.tsx b/src/actions/repay.tsx index 0452747..703ddc1 100644 --- a/src/actions/repay.tsx +++ b/src/actions/repay.tsx @@ -13,7 +13,7 @@ import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../constants/ids"; import { findOrCreateAccountByMint } from "./account"; import { LendingObligation, TokenAccount } from "../models"; import { ParsedAccount } from "../contexts/accounts"; -import { decimalToLamports } from "../utils/utils"; +import { wadToLamports } from "../utils/utils"; export const repay = async ( from: TokenAccount, // CollateralAccount @@ -76,7 +76,7 @@ export const repay = async ( signers ); - const loanRatio = amountLamports / decimalToLamports(obligation.info.borrowAmount) + const loanRatio = amountLamports / wadToLamports(obligation.info.borrowAmountWad) .toNumber(); console.log(loanRatio); diff --git a/src/components/AppBar/index.tsx b/src/components/AppBar/index.tsx index fb2fbe6..22b19a5 100644 --- a/src/components/AppBar/index.tsx +++ b/src/components/AppBar/index.tsx @@ -4,6 +4,7 @@ import { useWallet } from "../../contexts/wallet"; import { CurrentUserBadge } from "../CurrentUserBadge"; import { SettingOutlined } from "@ant-design/icons"; import { Settings } from "../Settings"; +import { LABELS } from "../../constants"; export const AppBar = (props: { left?: JSX.Element; right?: JSX.Element }) => { const { connected, wallet } = useWallet(); @@ -19,20 +20,20 @@ export const AppBar = (props: { left?: JSX.Element; right?: JSX.Element }) => { onClick={connected ? wallet.disconnect : wallet.connect} style={{ color: "#2abdd2" }} > - Connect + {LABELS.CONNECT_BUTTON} )} {connected && ( )} } trigger="click" > diff --git a/src/components/BorrowInput/index.tsx b/src/components/BorrowInput/index.tsx index 3cb23f8..a4cfc70 100644 --- a/src/components/BorrowInput/index.tsx +++ b/src/components/BorrowInput/index.tsx @@ -11,6 +11,7 @@ import { borrow } from "../../actions"; import { PublicKey } from "@solana/web3.js"; import { CollateralSelector } from "./../CollateralSelector"; import "./style.less"; +import { LABELS } from "../../constants"; export const BorrowInput = (props: { className?: string; @@ -84,7 +85,7 @@ export const BorrowInput = (props: { }} >
- How much would you like to borrow? + {LABELS.BORROW_QUESTION}
@@ -104,7 +105,7 @@ export const BorrowInput = (props: { />
{name}
-
Select collateral account?
+
{LABELS.SELECT_COLLATERAL}
- Borrow + {LABELS.BORROW_ACTION} diff --git a/src/components/ConnectButton/index.tsx b/src/components/ConnectButton/index.tsx new file mode 100644 index 0000000..38764c3 --- /dev/null +++ b/src/components/ConnectButton/index.tsx @@ -0,0 +1,13 @@ +import { Button } from "antd" +import { ButtonProps } from "antd/lib/button" +import React from "react" +import { useWallet } from "../../contexts/wallet"; +import { LABELS } from './../../constants'; + +export const ConnectButton = (props: ButtonProps & React.RefAttributes) => { + const { wallet, connected } = useWallet(); + const { onClick, children, ...rest } = props; + return +} \ No newline at end of file diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index 1f5f0d1..7633fc4 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -14,6 +14,7 @@ import BasicLayout from "@ant-design/pro-layout"; import { AppBar } from "./../AppBar"; import { Link, useLocation } from "react-router-dom"; import { useConnectionConfig } from "../../contexts/connection"; +import { LABELS } from "../../constants"; export const AppLayout = (props: any) => { const { env } = useConnectionConfig(); @@ -36,11 +37,11 @@ export const AppLayout = (props: any) => {
- Oyster Lending is unaudited software. Use at your own risk. + {LABELS.AUDIT_WARNING}
{ pathname: "/", }} > - Home + {LABELS.MENU_HOME} }> @@ -71,7 +72,7 @@ export const AppLayout = (props: any) => { pathname: "/dashboard", }} > - Dashboard + {LABELS.MENU_DASHBOARD} }> @@ -80,7 +81,7 @@ export const AppLayout = (props: any) => { pathname: "/deposit", }} > - Deposit + {LABELS.MENU_DEPOSIT} }> @@ -89,7 +90,7 @@ export const AppLayout = (props: any) => { pathname: "/borrow", }} > - Borrow + {LABELS.MENU_BORROW} {env !== "mainnet-beta" && ( @@ -99,7 +100,7 @@ export const AppLayout = (props: any) => { pathname: "/faucet", }} > - Faucet + {LABELS.MENU_FAUCET} )} diff --git a/src/components/RepayInput/index.tsx b/src/components/RepayInput/index.tsx index fc7de8a..fc97226 100644 --- a/src/components/RepayInput/index.tsx +++ b/src/components/RepayInput/index.tsx @@ -14,7 +14,8 @@ import { useWallet } from "../../contexts/wallet"; import { repay } from "../../actions"; import { CollateralSelector } from "./../CollateralSelector"; import "./style.less"; -import { decimalToLamports, formatNumber, fromLamports, toLamports } from "../../utils/utils"; +import { wadToLamports, formatNumber, fromLamports, toLamports } from "../../utils/utils"; +import { LABELS } from "../../constants"; export const RepayInput = (props: { className?: string; @@ -51,9 +52,9 @@ export const RepayInput = (props: { const lamports = useMemo(() => toLamports(parseFloat(value), repayLiquidityMint), [value, repayLiquidityMint]); - const mark = decimalToLamports(obligation?.info.borrowAmount).toNumber() / lamports * 100; + const mark = wadToLamports(obligation?.info.borrowAmountWad).toNumber() / lamports * 100; - const onReoay = useCallback(() => { + const onRepay = useCallback(() => { if ( !collateralReserve || !obligation || @@ -102,7 +103,7 @@ export const RepayInput = (props: { }} >
- How much would you like to repay? (Currently:{" "} + {LABELS.REPAY_QUESTION} (Currently:{" "}) {formatNumber.format(balance)} {name})
@@ -126,8 +127,8 @@ export const RepayInput = (props: { - setValue((fromLamports(decimalToLamports(obligation?.info.borrowAmount).toNumber(), repayLiquidityMint) * val / 100).toFixed(2))} /> -
Select collateral account?
+ setValue((fromLamports(wadToLamports(obligation?.info.borrowAmountWad).toNumber(), repayLiquidityMint) * val / 100).toFixed(2))} /> +
{LABELS.SELECT_COLLATERAL}
- Repay + {LABELS.REPAY_ACTION}
diff --git a/src/components/ReserveStatus/index.tsx b/src/components/ReserveStatus/index.tsx index 4594b5c..0564e22 100644 --- a/src/components/ReserveStatus/index.tsx +++ b/src/components/ReserveStatus/index.tsx @@ -3,6 +3,7 @@ import { LendingReserve } from "../../models/lending"; import { Card } from "antd"; import { PublicKey } from "@solana/web3.js"; import "./style.less"; +import { LABELS } from "../../constants"; export const ReserveStatus = (props: { className?: string; @@ -18,7 +19,7 @@ export const ReserveStatus = (props: { return ( Reserve Status & Configuration} + title={<>{LABELS.RESERVE_STATUS_TITLE}} bodyStyle={bodyStyle} >
- {formatNumber.format(borrowed)} {name} + {formatNumber.format(totalBorrowed)} {name}
diff --git a/src/components/WithdrawInput/index.tsx b/src/components/WithdrawInput/index.tsx index 2e28cb1..c6efe8e 100644 --- a/src/components/WithdrawInput/index.tsx +++ b/src/components/WithdrawInput/index.tsx @@ -13,6 +13,7 @@ import { useWallet } from "../../contexts/wallet"; import { withdraw } from "../../actions"; import { PublicKey } from "@solana/web3.js"; import "./style.less"; +import { LABELS } from "../../constants"; export const WithdrawInput = (props: { className?: string; @@ -76,7 +77,7 @@ export const WithdrawInput = (props: { }} >
- How much would you like to withdraw? + {LABELS.WITHDRAW_QUESTION}
@@ -102,7 +103,7 @@ export const WithdrawInput = (props: { onClick={onWithdraw} disabled={fromAccounts.length === 0} > - Withdraw + {LABELS.WITHDRAW_ACTION}
diff --git a/src/constants/index.tsx b/src/constants/index.tsx new file mode 100644 index 0000000..f70b28e --- /dev/null +++ b/src/constants/index.tsx @@ -0,0 +1,3 @@ +export * from './ids'; +export * from './labels'; +export * from './math'; diff --git a/src/constants/labels.ts b/src/constants/labels.ts new file mode 100644 index 0000000..97ac495 --- /dev/null +++ b/src/constants/labels.ts @@ -0,0 +1,30 @@ +export const LABELS = { + CONNECT_LABEL: "Connect Wallet", + GIVE_SOL: "Give me SOL", + FAUCET_INFO: "This faucet will help you fund your accounts outside of Solana main network.", + ACCOUNT_FUNDED: "Account funded.", + REPAY_QUESTION: "How much would you like to repay?", + REPAY_ACTION: "Repay", + RESERVE_STATUS_TITLE: "Reserve Status & Configuration", + AUDIT_WARNING: "Oyster Lending is unaudited software. Use at your own risk.", + MENU_HOME: "Home", + MENU_DASHBOARD: "Dashboard", + MENU_DEPOSIT: "Deposit", + MENU_BORROW: "Borrow", + MENU_FAUCET: "Faucet", + APP_TITLE: "Oyster Lending", + CONNECT_BUTTON: "Connect", + WALLET_TOOLTIP: "Wallet public key", + SETTINGS_TOOLTIP: "Settings", + SELECT_COLLATERAL: "Select collateral account?", + BORROW_QUESTION: "How much would you like to borrow?", + BORROW_ACTION: "Borrow", + TABLE_TITLE_ASSET: "Asset", + TABLE_TITLE_LOAN_BALANCE: "Your loan balan", + TABLE_TITLE_APY: "APY", + TABLE_TITLE_ACTION: "Action", + DASHBOARD_TITLE_LOANS: "Loans", + DASHBOARD_TITLE_DEPOSITS: "Deposts", + WITHDRAW_ACTION: "Withdraw", + WITHDRAW_QUESTION: "How much would you like to withdraw?", +} \ No newline at end of file diff --git a/src/constants/math.ts b/src/constants/math.ts new file mode 100644 index 0000000..f01ed86 --- /dev/null +++ b/src/constants/math.ts @@ -0,0 +1,6 @@ +import BN from "bn.js"; + +export const TEN = new BN(10); +export const WAD = TEN.pow(new BN(18)); +export const RAY = TEN.pow(new BN(27)); +export const ZERO = new BN(0); \ No newline at end of file diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 69fa002..d52ecbb 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -7,3 +7,4 @@ export * from "./useCollateralBalance"; export * from "./useLendingObligations"; export * from "./useUserObligations"; export * from "./useUserObligationByReserve"; +export * from "./useBorrowedAmount"; diff --git a/src/hooks/useBorrowedAmount.ts b/src/hooks/useBorrowedAmount.ts new file mode 100644 index 0000000..7a519ca --- /dev/null +++ b/src/hooks/useBorrowedAmount.ts @@ -0,0 +1,53 @@ +import { useEffect, useMemo, useState } from "react"; +import { useUserAccounts } from "./useUserAccounts"; +import { useLendingObligations } from "./useLendingObligations"; +import { TokenAccount } from "../models"; +import { PublicKey } from "@solana/web3.js"; +import { useUserObligationByReserve } from "./useUserObligationByReserve"; +import { fromLamports, wadToLamports } from "../utils/utils"; +import { cache, getMultipleAccounts, MintParser, ParsedAccount, useMint } from "../contexts/accounts"; +import { useConnection } from "../contexts/connection"; +import { MintInfo } from "@solana/spl-token"; +import { useLendingReserve } from "./useLendingReserves"; + +export function useBorrowedAmount(address?: string | PublicKey) { + const connection = useConnection(); + const { userObligationsByReserve } = useUserObligationByReserve(address); + const [borrowedLamports, setBorrowedLamports] = useState(0); + const reserve = useLendingReserve(address); + const liquidityMint = useMint(reserve?.info.liquidityMint); + + useEffect(() => { + setBorrowedLamports(0); + + (async () => { + // precache obligation mints + const { keys, array } = await getMultipleAccounts( + connection, + 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) => { + + 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; + + result += borrowed * owned / obligationMint?.info.supply.toNumber(); + return result + + }, 0)); + })(); + + + }, [userObligationsByReserve]); + + return { borrowed: fromLamports(borrowedLamports, liquidityMint), borrowedLamports }; +} diff --git a/src/hooks/useLendingReserves.ts b/src/hooks/useLendingReserves.ts index c9ab926..1c728c9 100644 --- a/src/hooks/useLendingReserves.ts +++ b/src/hooks/useLendingReserves.ts @@ -34,14 +34,14 @@ export function useLendingReserves() { }; } -export function useLendingReserve(address: string | PublicKey) { +export function useLendingReserve(address?: string | PublicKey) { const id = typeof address === "string" ? address : address?.toBase58(); const [reserveAccount, setReserveAccount] = useState< ParsedAccount >(); 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 cf624d6..7d9ce4b 100644 --- a/src/hooks/useUserObligationByReserve.ts +++ b/src/hooks/useUserObligationByReserve.ts @@ -2,15 +2,16 @@ import { useMemo } from "react"; import { useUserObligations } from "./useUserObligations"; import { PublicKey } from "@solana/web3.js"; -export function useUserObligationByReserve(reserve: PublicKey) { +export function useUserObligationByReserve(reserve?: string | PublicKey) { const { userObligations } = useUserObligations(); const userObligationsByReserve = useMemo( - () => - userObligations.filter((item) => - item.oblication.info.borrowReserve.equals(reserve) - ), - [reserve, userObligations] + () => { + const id = typeof reserve === 'string' ? reserve : reserve?.toBase58(); + return userObligations.filter((item) => + item.obligation.info.borrowReserve.toBase58() === id + ) + }, [reserve, userObligations] ); return { diff --git a/src/hooks/useUserObligations.ts b/src/hooks/useUserObligations.ts index f017ce7..fb49dd3 100644 --- a/src/hooks/useUserObligations.ts +++ b/src/hooks/useUserObligations.ts @@ -26,7 +26,7 @@ export function useUserObligations() { ) .map((ob) => { return { - oblication: ob, + obligation: ob, userAccounts: [...accountsByMint.get(ob.info.tokenMint.toBase58())], // TODO: add total borrowed amount? diff --git a/src/models/lending/obligation.ts b/src/models/lending/obligation.ts index daeaf35..b70e11c 100644 --- a/src/models/lending/obligation.ts +++ b/src/models/lending/obligation.ts @@ -12,9 +12,9 @@ export const LendingObligationLayout: typeof BufferLayout.Structure = BufferLayo /// Reserve which collateral tokens were deposited into Layout.publicKey("collateralSupply"), /// Borrow rate used for calculating interest. - Layout.uint128("cumulativeBorrowRate"), + Layout.uint128("cumulativeBorrowRateWad"), /// Amount of tokens borrowed for this obligation plus interest - Layout.uint128("borrowAmount"), + Layout.uint128("borrowAmountWad"), /// Reserve which tokens were borrowed from Layout.publicKey("borrowReserve"), /// Mint address of the tokens for this obligation @@ -30,8 +30,8 @@ export interface LendingObligation { lastUpdateSlot: BN; collateralAmount: BN; collateralSupply: PublicKey; - cumulativeBorrowRate: BN; // decimals - borrowAmount: BN; // decimals + cumulativeBorrowRateWad: BN; // decimals + borrowAmountWad: BN; // decimals borrowReserve: PublicKey; tokenMint: PublicKey; } diff --git a/src/models/lending/reserve.ts b/src/models/lending/reserve.ts index 416902a..428d199 100644 --- a/src/models/lending/reserve.ts +++ b/src/models/lending/reserve.ts @@ -7,6 +7,7 @@ import { } from "@solana/web3.js"; import BN from "bn.js"; import * as BufferLayout from "buffer-layout"; +import { WAD } from "../../constants"; import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids"; import * as Layout from "./../../utils/layout"; import { LendingInstruction } from "./lending"; @@ -26,20 +27,26 @@ export const LendingReserveLayout: typeof BufferLayout.Structure = BufferLayout. BufferLayout.struct( [ - /// Max utilization rate as a percent - BufferLayout.u8("maxUtilizationRate"), + /// Optimal utilization rate as a percent + BufferLayout.u8("optimalUtilizationRate"), /// The ratio of the loan to the value of the collateral as a percent BufferLayout.u8("loanToValueRatio"), /// The percent discount the liquidator gets when buying collateral for an unhealthy obligation BufferLayout.u8("liquidationBonus"), /// The percent at which an obligation is considered unhealthy BufferLayout.u8("liquidationThreshold"), + /// Min borrow APY + BufferLayout.u8("minBorrowRate"), + /// Optimal (utilization) borrow APY + BufferLayout.u8("optimalBorrowRate"), + /// Max borrow APY + BufferLayout.u8("maxBorrowRate"), ], "config" ), - Layout.uint128("cumulativeBorrowRate"), - Layout.uint128("totalBorrows"), + Layout.uint128("cumulativeBorrowRateWad"), + Layout.uint128("totalBorrowsWad"), Layout.uint64("totalLiquidity"), Layout.uint64("collateralMintSupply"), @@ -66,15 +73,18 @@ export interface LendingReserve { dexMarketPrice: BN; // what is precision on the price? config: { - maxUtilizationRate: number; + optimalUtilizationRate: number; loanToValueRatio: number; liquidationBonus: number; liquidationThreshold: number; + minBorrowRate: number; + optimalBorrowRate: number; + maxBorrowRate: number; }; // collateralFactor: number; - cumulativeBorrowRate: BN; - totalBorrows: BN; + cumulativeBorrowRateWad: BN; + totalBorrowsWad: BN; totalLiquidity: BN; collateralMintSupply: BN; @@ -250,3 +260,23 @@ export const withdrawInstruction = ( data, }); }; + +export const calculateBorrowAPY = (reserve: LendingReserve) => { + 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; + } else { + 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; + } + + return borrowAPY; +} \ No newline at end of file diff --git a/src/routes.tsx b/src/routes.tsx index 0f6de51..60c3deb 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -54,7 +54,7 @@ export function Routes() { children={} /> } /> { + const name = useTokenName(props.reserve.liquidityMint); + const { balance: tokenBalance } = useUserBalance(props.reserve.liquidityMint); + const { balance: collateralBalance } = useCollateralBalance(props.reserve); + + return ( + + +
+ + + {name} + +
+ {formatNumber.format(tokenBalance)} {name} +
+
+ {formatNumber.format(collateralBalance)} {name} +
+
--
+
+ +
+
+
+ + ); +}; diff --git a/src/views/dashboard/index.tsx b/src/views/dashboard/index.tsx index 14dab49..7e594a7 100644 --- a/src/views/dashboard/index.tsx +++ b/src/views/dashboard/index.tsx @@ -1,22 +1,27 @@ import React from "react"; +import { LABELS } from "../../constants"; import { useUserObligations } from "./../../hooks"; import { ObligationItem } from "./obligationItem"; +import "./style.less" export const DashboardView = () => { const { userObligations } = useUserObligations(); return ( -
+
- Loans - {userObligations.length > 0 &&
-
Asset
-
Your loan balance
-
APY
-
Action
+ {LABELS.DASHBOARD_TITLE_DEPOSITS} +
+
+ {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.map((item) => { - return ; + return ; })}
diff --git a/src/views/dashboard/obligationItem.tsx b/src/views/dashboard/obligationItem.tsx index dcab7dd..7eb9517 100644 --- a/src/views/dashboard/obligationItem.tsx +++ b/src/views/dashboard/obligationItem.tsx @@ -3,7 +3,7 @@ import { useTokenName } from "../../hooks"; import { LendingObligation, LendingReserve } from "../../models/lending"; import { TokenIcon } from "../../components/TokenIcon"; import { - decimalToLamports, + wadToLamports, formatNumber, fromLamports, } from "../../utils/utils"; @@ -25,16 +25,16 @@ export const ObligationItem = (props: { const liquidityMint = useMint(borrowReserve.info.liquidityMint); const borrowAmount = fromLamports( - decimalToLamports(obligation.info.borrowAmount), + wadToLamports(obligation.info.borrowAmountWad), liquidityMint ); return ( -
+
{name} diff --git a/src/views/dashboard/itemStyle.less b/src/views/dashboard/style.less similarity index 89% rename from src/views/dashboard/itemStyle.less rename to src/views/dashboard/style.less index 4a3fe1b..ed46ad7 100644 --- a/src/views/dashboard/itemStyle.less +++ b/src/views/dashboard/style.less @@ -1,4 +1,4 @@ -.borrow-item { +.dashboard-item { display: flex; justify-content: space-between; align-items: center; @@ -14,7 +14,7 @@ } } -.borrow-header { +.dashboard-header { margin: 0px 30px; & > div { diff --git a/src/views/faucet/index.tsx b/src/views/faucet/index.tsx index ab8b68e..b7f2009 100644 --- a/src/views/faucet/index.tsx +++ b/src/views/faucet/index.tsx @@ -1,9 +1,11 @@ import React, { useCallback } from "react"; -import { Button, Card } from "antd"; +import { Card } from "antd"; import { useConnection } from "../../contexts/connection"; import { useWallet } from "../../contexts/wallet"; import { LAMPORTS_PER_SOL } from "@solana/web3.js"; import { notify } from "../../utils/notifications"; +import { ConnectButton } from "./../../components/ConnectButton"; +import { LABELS } from "../../constants"; export const FaucetView = () => { const connection = useConnection(); @@ -14,7 +16,7 @@ export const FaucetView = () => { .requestAirdrop(wallet.publicKey, 2 * LAMPORTS_PER_SOL) .then(() => { notify({ - message: "Account funded.", + message: LABELS.ACCOUNT_FUNDED, type: "success", }); }); @@ -40,12 +42,11 @@ export const FaucetView = () => { }} >
- This Faucet will help you fund your accounts outside of Solana main - network. + {LABELS.FAUCET_INFO}
- + + {LABELS.GIVE_SOL} +
diff --git a/src/views/home/item.tsx b/src/views/home/item.tsx index c7e2829..4c71f29 100644 --- a/src/views/home/item.tsx +++ b/src/views/home/item.tsx @@ -1,12 +1,13 @@ import React from "react"; import { useTokenName } from "../../hooks"; -import { LendingReserve } from "../../models/lending"; +import { calculateBorrowAPY, LendingReserve } from "../../models/lending"; import { TokenIcon } from "../../components/TokenIcon"; -import { decimalToLamports, formatNumber, fromLamports } from "../../utils/utils"; +import { wadToLamports, formatNumber, fromLamports } 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; @@ -21,7 +22,8 @@ export const LendingReserveItem = (props: { liquidityMint ); - const totalBorrows = decimalToLamports(props.reserve.totalBorrows).toNumber(); + console.log(props.reserve.totalBorrowsWad.toString()); + const totalBorrows = fromLamports(wadToLamports(props.reserve.totalBorrowsWad), liquidityMint); console.log(liquidityMint); @@ -40,9 +42,12 @@ export const LendingReserveItem = (props: { {formatNumber.format(totalBorrows)} {name}
--
-
--
+
{calculateBorrowAPY(props.reserve)}
); }; + + + diff --git a/src/views/repayReserve/index.tsx b/src/views/repayReserve/index.tsx index 8c16a27..31a94b6 100644 --- a/src/views/repayReserve/index.tsx +++ b/src/views/repayReserve/index.tsx @@ -12,11 +12,12 @@ import "./style.less"; export const RepayReserveView = () => { const { reserve: reserveId, obligation: obligationId } = useParams<{ - reserve: string; + reserve?: string; obligation?: string; }>(); - const lendingReserve = useLendingReserve(reserveId); + const lendingObligation = useLendingObligation(obligationId); + const lendingReserve = useLendingReserve(obligationId ? lendingObligation?.info.borrowReserve : reserveId); const reserve = lendingReserve?.info; console.log([reserveId, obligationId]);