From 5ea0434a68bbd2865ba70a74b818bec6ca57a27a Mon Sep 17 00:00:00 2001 From: bartosz-lipinski <264380+bartosz-lipinski@users.noreply.github.com> Date: Fri, 20 Nov 2020 23:54:50 -0600 Subject: [PATCH] chore: prettier --- .vscode/settings.json | 4 +- src/App.tsx | 5 +- src/actions/account.ts | 68 ++++--- src/actions/borrow.tsx | 71 ++++--- src/actions/deposit.tsx | 62 +++--- src/actions/index.ts | 8 +- src/actions/withdraw.tsx | 15 +- src/components/AppBar/index.tsx | 68 +++---- src/components/BorrowInput/index.tsx | 196 +++++++++++-------- src/components/CurrentUserBadge/index.tsx | 6 +- src/components/DepositInfoLine/index.tsx | 58 +++--- src/components/DepositInput/index.tsx | 95 +++++---- src/components/Identicon/index.tsx | 9 +- src/components/Input/numeric.tsx | 2 +- src/components/Layout/index.tsx | 133 +++++++------ src/components/ReserveStatus/index.tsx | 49 +++-- src/components/SideReserveOverview/index.tsx | 150 +++++++------- src/components/TokenIcon/index.tsx | 4 +- src/components/UserLendingCard/index.tsx | 146 +++++++------- src/components/WithdrawInput/index.tsx | 125 +++++++----- src/constants/ids.tsx | 2 +- src/contexts/accounts.tsx | 106 +++++----- src/contexts/connection.tsx | 13 +- src/contexts/lending.tsx | 80 +++++--- src/contexts/market.tsx | 19 +- src/hooks/index.ts | 12 +- src/hooks/useAccountByMint.ts | 2 +- src/hooks/useCollateralBalance.ts | 4 +- src/hooks/useLendingReserves.ts | 23 ++- src/hooks/useTokenName.ts | 5 +- src/hooks/useUserAccounts.ts | 12 +- src/hooks/useUserBalance.ts | 12 +- src/models/dex/index.ts | 2 +- src/models/dex/market.ts | 18 +- src/models/index.ts | 2 +- src/models/lending/borrow.ts | 18 +- src/models/lending/index.ts | 10 +- src/models/lending/lending.ts | 4 +- src/models/lending/market.ts | 20 +- src/models/lending/obligation.ts | 34 ++-- src/models/lending/reserve.ts | 53 ++--- src/routes.tsx | 26 ++- src/utils/eventEmitter.ts | 2 +- src/utils/layout.ts | 17 +- src/utils/utils.ts | 15 +- src/views/borrow/index.tsx | 12 +- src/views/borrow/item.tsx | 42 ++-- src/views/borrowReserve/index.tsx | 43 ++-- src/views/dashboard/index.tsx | 14 +- src/views/deposit/index.tsx | 2 +- src/views/deposit/view/index.tsx | 12 +- src/views/deposit/view/item.tsx | 50 +++-- src/views/depositReserve/index.tsx | 48 +++-- src/views/faucet/index.tsx | 33 ++-- src/views/home/index.tsx | 28 +-- src/views/home/item.tsx | 46 +++-- src/views/index.tsx | 18 +- src/views/reserve/index.tsx | 38 ++-- src/views/withdraw/index.tsx | 48 +++-- 59 files changed, 1274 insertions(+), 945 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index ff30c44..78664b2 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "editor.tabSize": 2 -} \ No newline at end of file + "editor.tabSize": 2 +} diff --git a/src/App.tsx b/src/App.tsx index 9bc8981..21da649 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -2,11 +2,8 @@ import React from "react"; import "./App.less"; import { Routes } from "./routes"; - function App() { - return ( - - ); + return ; } export default App; diff --git a/src/actions/account.ts b/src/actions/account.ts index 41c5c6a..883530c 100644 --- a/src/actions/account.ts +++ b/src/actions/account.ts @@ -1,8 +1,13 @@ import { AccountLayout, Token } from "@solana/spl-token"; -import { Account, PublicKey, SystemProgram, TransactionInstruction } from "@solana/web3.js"; +import { + Account, + PublicKey, + SystemProgram, + TransactionInstruction, +} from "@solana/web3.js"; import { TOKEN_PROGRAM_ID, WRAPPED_SOL_MINT } from "../constants/ids"; import { TokenAccount } from "../models"; -import { cache, TokenAccountParser } from './../contexts/accounts'; +import { cache, TokenAccountParser } from "./../contexts/accounts"; export function ensureSplAccount( instructions: TransactionInstruction[], @@ -17,10 +22,11 @@ export function ensureSplAccount( } const account = createUninitializedAccount( - instructions, - payer, - amount, - signers); + instructions, + payer, + amount, + signers + ); instructions.push( Token.createInitAccountInstruction( @@ -47,10 +53,11 @@ export function ensureSplAccount( export const DEFAULT_TEMP_MEM_SPACE = 65528; export function createTempMemoryAccount( - instructions: TransactionInstruction[], - payer: PublicKey, + instructions: TransactionInstruction[], + payer: PublicKey, signers: Account[], - space = DEFAULT_TEMP_MEM_SPACE) { + space = DEFAULT_TEMP_MEM_SPACE +) { const account = new Account(); instructions.push( SystemProgram.createAccount({ @@ -68,12 +75,12 @@ export function createTempMemoryAccount( return account.publicKey; } - export function createUninitializedAccount( - instructions: TransactionInstruction[], - payer: PublicKey, + instructions: TransactionInstruction[], + payer: PublicKey, amount: number, - signers: Account[]) { + signers: Account[] +) { const account = new Account(); instructions.push( SystemProgram.createAccount({ @@ -96,21 +103,17 @@ export function createTokenAccount( accountRentExempt: number, mint: PublicKey, owner: PublicKey, - signers: Account[], + signers: Account[] ) { const account = createUninitializedAccount( - instructions, - payer, + instructions, + payer, accountRentExempt, - signers); + signers + ); instructions.push( - Token.createInitAccountInstruction( - TOKEN_PROGRAM_ID, - mint, - account, - owner - ) + Token.createInitAccountInstruction(TOKEN_PROGRAM_ID, mint, account, owner) ); return account; @@ -128,15 +131,16 @@ export function findOrCreateAccountByMint( excluded?: Set ): PublicKey { const accountToFind = mint.toBase58(); - const account = cache.byParser(TokenAccountParser) - .map(id => cache.get(id)) + const account = cache + .byParser(TokenAccountParser) + .map((id) => cache.get(id)) .find( - (acc) => - acc !== undefined && - acc.info.mint.toBase58() === accountToFind && - acc.info.owner.toBase58() === owner.toBase58() && - (excluded === undefined || !excluded.has(acc.pubkey.toBase58())) - ); + (acc) => + acc !== undefined && + acc.info.mint.toBase58() === accountToFind && + acc.info.owner.toBase58() === owner.toBase58() && + (excluded === undefined || !excluded.has(acc.pubkey.toBase58())) + ); const isWrappedSol = accountToFind === WRAPPED_SOL_MINT.toBase58(); let toAccount: PublicKey; @@ -150,7 +154,7 @@ export function findOrCreateAccountByMint( accountRentExempt, mint, owner, - signers, + signers ); if (isWrappedSol) { diff --git a/src/actions/borrow.tsx b/src/actions/borrow.tsx index bf7c2fd..fb4a178 100644 --- a/src/actions/borrow.tsx +++ b/src/actions/borrow.tsx @@ -9,11 +9,20 @@ import { notify } from "../utils/notifications"; import { LendingReserve } from "./../models/lending/reserve"; import { AccountLayout, MintInfo, MintLayout, Token } from "@solana/spl-token"; import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../constants/ids"; -import { createTempMemoryAccount, createUninitializedAccount, ensureSplAccount, findOrCreateAccountByMint } from "./account"; +import { + createTempMemoryAccount, + createUninitializedAccount, + ensureSplAccount, + findOrCreateAccountByMint, +} from "./account"; import { cache, MintParser, ParsedAccount } from "../contexts/accounts"; -import { TokenAccount, LendingObligationLayout, borrowInstruction, LendingMarket } from "../models"; +import { + TokenAccount, + LendingObligationLayout, + borrowInstruction, + LendingMarket, +} from "../models"; import { toLamports } from "../utils/utils"; -import { DexMarketParser } from "../models/dex"; export const borrow = async ( from: TokenAccount, @@ -26,8 +35,8 @@ export const borrow = async ( depositReserveAddress: PublicKey, connection: Connection, - wallet: any) => { - + wallet: any +) => { notify({ message: "Borrowing funds...", description: "Please review transactions to approve.", @@ -48,23 +57,21 @@ export const borrow = async ( await connection.getMinimumBalanceForRentExemption( LendingObligationLayout.span ), - signers, + signers ); const obligationMint = createUninitializedAccount( instructions, wallet.publicKey, - await connection.getMinimumBalanceForRentExemption( - MintLayout.span - ), - signers, + await connection.getMinimumBalanceForRentExemption(MintLayout.span), + signers ); const obligationTokenOutput = createUninitializedAccount( instructions, wallet.publicKey, accountRentExempt, - signers, + signers ); let toAccount = await findOrCreateAccountByMint( @@ -78,7 +85,9 @@ export const borrow = async ( ); // create all accounts in one transaction - let tx = await sendTransaction(connection, wallet, instructions, [...signers]); + let tx = await sendTransaction(connection, wallet, instructions, [ + ...signers, + ]); notify({ message: "Obligation accounts created", @@ -101,7 +110,11 @@ export const borrow = async ( LENDING_PROGRAM_ID ); - const mint = (await cache.query(connection, depositReserve.collateralMint, MintParser)) as ParsedAccount; + const mint = (await cache.query( + connection, + depositReserve.collateralMint, + MintParser + )) as ParsedAccount; const amountLamports = toLamports(amount, mint?.info); const fromAccount = ensureSplAccount( @@ -121,30 +134,36 @@ export const borrow = async ( authority, wallet.publicKey, [], - amountLamports, + amountLamports ) ); - const market = cache.get(depositReserve.lendingMarket) as ParsedAccount; - - const dexMarketAddress = borrowReserve.dexMarketOption ? borrowReserve.dexMarket : depositReserve.dexMarket; + const market = cache.get(depositReserve.lendingMarket) as ParsedAccount< + LendingMarket + >; + + const dexMarketAddress = borrowReserve.dexMarketOption + ? borrowReserve.dexMarket + : depositReserve.dexMarket; const dexMarket = cache.get(dexMarketAddress); - if(!dexMarket) { - throw new Error(`Dex market doesn't exsists.`) + if (!dexMarket) { + throw new Error(`Dex market doesn't exsists.`); } - const dexOrderBookSide = market.info.quoteMint.equals(depositReserve.liquidityMint) ? - dexMarket?.info.bids : - dexMarket?.info.asks + const dexOrderBookSide = market.info.quoteMint.equals( + depositReserve.liquidityMint + ) + ? dexMarket?.info.bids + : dexMarket?.info.asks; const memory = createTempMemoryAccount( instructions, wallet.publicKey, - signers, + signers ); - // deposit + // deposit instructions.push( borrowInstruction( amountLamports, @@ -165,7 +184,7 @@ export const borrow = async ( dexMarketAddress, dexOrderBookSide, - memory, + memory ) ); try { @@ -185,4 +204,4 @@ export const borrow = async ( } catch { // TODO: } -} +}; diff --git a/src/actions/deposit.tsx b/src/actions/deposit.tsx index 82bd69f..5b623bd 100644 --- a/src/actions/deposit.tsx +++ b/src/actions/deposit.tsx @@ -6,10 +6,18 @@ import { } from "@solana/web3.js"; import { sendTransaction } from "../contexts/connection"; import { notify } from "../utils/notifications"; -import { depositInstruction, initReserveInstruction, LendingReserve } from "./../models/lending/reserve"; +import { + depositInstruction, + initReserveInstruction, + LendingReserve, +} from "./../models/lending/reserve"; import { AccountLayout, MintInfo, Token } from "@solana/spl-token"; import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../constants/ids"; -import { createUninitializedAccount, ensureSplAccount, findOrCreateAccountByMint } from "./account"; +import { + createUninitializedAccount, + ensureSplAccount, + findOrCreateAccountByMint, +} from "./account"; import { cache, MintParser, ParsedAccount } from "../contexts/accounts"; import { TokenAccount } from "../models"; import { toLamports } from "../utils/utils"; @@ -20,8 +28,8 @@ export const deposit = async ( reserve: LendingReserve, reserveAddress: PublicKey, connection: Connection, - wallet: any) => { - + wallet: any +) => { // TODO: customize ? const MAX_UTILIZATION_RATE = 80; @@ -47,7 +55,11 @@ export const deposit = async ( LENDING_PROGRAM_ID ); - const mint = (await cache.query(connection, reserve.liquidityMint, MintParser)) as ParsedAccount; + const mint = (await cache.query( + connection, + reserve.liquidityMint, + MintParser + )) as ParsedAccount; const amountLamports = toLamports(amount, mint?.info); const fromAccount = ensureSplAccount( @@ -67,7 +79,7 @@ export const deposit = async ( authority, wallet.publicKey, [], - amountLamports, + amountLamports ) ); @@ -88,12 +100,12 @@ export const deposit = async ( instructions, wallet.publicKey, accountRentExempt, - signers, + signers ); } if (isInitalized) { - // deposit + // deposit instructions.push( depositInstruction( amountLamports, @@ -102,25 +114,27 @@ export const deposit = async ( authority, reserveAddress, reserve.liquiditySupply, - reserve.collateralMint, + reserve.collateralMint ) ); } else { // TODO: finish reserve init - instructions.push(initReserveInstruction( - amountLamports, - MAX_UTILIZATION_RATE, - fromAccount, - toAccount, - reserveAddress, - reserve.liquidityMint, - reserve.liquiditySupply, - reserve.collateralMint, - reserve.collateralSupply, - reserve.lendingMarket, - authority, - reserve.dexMarket, - )); + instructions.push( + initReserveInstruction( + amountLamports, + MAX_UTILIZATION_RATE, + fromAccount, + toAccount, + reserveAddress, + reserve.liquidityMint, + reserve.liquiditySupply, + reserve.collateralMint, + reserve.collateralSupply, + reserve.lendingMarket, + authority, + reserve.dexMarket + ) + ); } try { @@ -140,4 +154,4 @@ export const deposit = async ( } catch { // TODO: } -} +}; diff --git a/src/actions/index.ts b/src/actions/index.ts index 81c8379..44c0bd0 100644 --- a/src/actions/index.ts +++ b/src/actions/index.ts @@ -1,4 +1,4 @@ -export { borrow } from './borrow'; -export { deposit } from './deposit'; -export { withdraw } from './withdraw'; -export * from './account'; +export { borrow } from "./borrow"; +export { deposit } from "./deposit"; +export { withdraw } from "./withdraw"; +export * from "./account"; diff --git a/src/actions/withdraw.tsx b/src/actions/withdraw.tsx index d1c6568..f3dc88a 100644 --- a/src/actions/withdraw.tsx +++ b/src/actions/withdraw.tsx @@ -6,7 +6,10 @@ import { } from "@solana/web3.js"; import { sendTransaction } from "../contexts/connection"; import { notify } from "../utils/notifications"; -import { LendingReserve, withdrawInstruction } from "./../models/lending/reserve"; +import { + LendingReserve, + withdrawInstruction, +} from "./../models/lending/reserve"; import { AccountLayout, Token } from "@solana/spl-token"; import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../constants/ids"; import { findOrCreateAccountByMint } from "./account"; @@ -18,8 +21,8 @@ export const withdraw = async ( reserve: LendingReserve, reserveAddress: PublicKey, connection: Connection, - wallet: any) => { - + wallet: any +) => { notify({ message: "Withdrawing funds...", description: "Please review transactions to approve.", @@ -50,7 +53,7 @@ export const withdraw = async ( authority, wallet.publicKey, [], - amountLamports, + amountLamports ) ); @@ -73,7 +76,7 @@ export const withdraw = async ( reserveAddress, reserve.collateralMint, reserve.liquiditySupply, - authority, + authority ) ); @@ -94,4 +97,4 @@ export const withdraw = async ( } catch { // TODO: } -} +}; diff --git a/src/components/AppBar/index.tsx b/src/components/AppBar/index.tsx index 33f9a4f..fb2fbe6 100644 --- a/src/components/AppBar/index.tsx +++ b/src/components/AppBar/index.tsx @@ -9,42 +9,42 @@ export const AppBar = (props: { left?: JSX.Element; right?: JSX.Element }) => { const { connected, wallet } = useWallet(); const TopBar = ( -
- -
- {!connected && ( - - )} - {connected && ( - - )} -
- } - trigger="click" +
+ +
+ {!connected && ( + + )} + {connected && ( + + )}
+ } + trigger="click" + > +
); return TopBar; diff --git a/src/components/BorrowInput/index.tsx b/src/components/BorrowInput/index.tsx index d8c1e2c..2bdf147 100644 --- a/src/components/BorrowInput/index.tsx +++ b/src/components/BorrowInput/index.tsx @@ -1,5 +1,5 @@ import React, { useCallback, useMemo, useState } from "react"; -import { useLendingReserves, useTokenName, useUserBalance } from '../../hooks'; +import { useLendingReserves, useTokenName, useUserBalance } from "../../hooks"; import { LendingReserve, LendingReserveParser } from "../../models"; import { TokenIcon } from "../TokenIcon"; import { getTokenName } from "../../utils/utils"; @@ -8,9 +8,9 @@ import { cache, ParsedAccount } from "../../contexts/accounts"; import { NumericInput } from "../Input/numeric"; import { useConnection, useConnectionConfig } from "../../contexts/connection"; import { useWallet } from "../../contexts/wallet"; -import { borrow } from '../../actions'; +import { borrow } from "../../actions"; import { PublicKey } from "@solana/web3.js"; -import './style.less'; +import "./style.less"; const { Option } = Select; @@ -22,60 +22,71 @@ const CollateralSelector = (props: { const { reserveAccounts } = useLendingReserves(); const { tokenMap } = useConnectionConfig(); - return { + if (props.onMintChange) { + props.onMintChange(item); + } + }} + filterOption={(input, option) => + option?.name?.toLowerCase().indexOf(input.toLowerCase()) >= 0 } - }} - filterOption={(input, option) => - option?.name?.toLowerCase().indexOf(input.toLowerCase()) >= 0 - } - > - {reserveAccounts - .filter(reserve => reserve.info !== props.reserve) - .map(reserve => { - const mint = reserve.info.liquidityMint.toBase58(); - const address = reserve.pubkey.toBase58(); - const name = getTokenName(tokenMap, mint); - return - })} - ; -} + > + {reserveAccounts + .filter((reserve) => reserve.info !== props.reserve) + .map((reserve) => { + const mint = reserve.info.liquidityMint.toBase58(); + const address = reserve.pubkey.toBase58(); + const name = getTokenName(tokenMap, mint); + return ( + + ); + })} + + ); +}; -export const BorrowInput = (props: { className?: string, reserve: LendingReserve, address: PublicKey }) => { +export const BorrowInput = (props: { + className?: string; + reserve: LendingReserve; + address: PublicKey; +}) => { const connection = useConnection(); const { wallet } = useWallet(); - const [value, setValue] = useState(''); + const [value, setValue] = useState(""); const borrowReserve = props.reserve; const borrowReserveAddress = props.address; const [collateralReserveMint, setCollateralReserveMint] = useState(); - const collateralReserve = useMemo(() => { - const id: string = cache.byParser(LendingReserveParser) - .find(acc => acc === collateralReserveMint) || ''; + const id: string = + cache + .byParser(LendingReserveParser) + .find((acc) => acc === collateralReserveMint) || ""; return cache.get(id) as ParsedAccount; - }, [collateralReserveMint]) - + }, [collateralReserveMint]); const name = useTokenName(borrowReserve?.liquidityMint); - const { - accounts: fromAccounts - } = useUserBalance(collateralReserve?.info.collateralMint); + const { accounts: fromAccounts } = useUserBalance( + collateralReserve?.info.collateralMint + ); // const collateralBalance = useUserBalance(reserve?.collateralMint); const onBorrow = useCallback(() => { @@ -91,50 +102,71 @@ export const BorrowInput = (props: { className?: string, reserve: LendingReserve collateralReserve.info, collateralReserve.pubkey, connection, - wallet); - }, [value, borrowReserve, fromAccounts, borrowReserveAddress]); + wallet + ); + }, [ + connection, + wallet, + value, + collateralReserve, + borrowReserve, + fromAccounts, + borrowReserveAddress, + ]); const bodyStyle: React.CSSProperties = { - display: 'flex', + display: "flex", flex: 1, - justifyContent: 'center', - alignItems: 'center', - height: '100%', + justifyContent: "center", + alignItems: "center", + height: "100%", }; - return - -
-
- How much would you like to borrow? -
-
- - { - setValue(val); - }} - autoFocus={true} - style={{ - fontSize: 20, - boxShadow: "none", - borderColor: "transparent", - outline: "transpaernt", - }} - placeholder="0.00" - /> -
{name}
-
-
- Select collateral account? -
- +
+
+ How much would you like to borrow? +
+
+ + { + setValue(val); + }} + autoFocus={true} + style={{ + fontSize: 20, + boxShadow: "none", + borderColor: "transparent", + outline: "transpaernt", + }} + placeholder="0.00" + /> +
{name}
+
+
Select collateral account?
+ - -
- ; -} \ No newline at end of file + +
+
+ ); +}; diff --git a/src/components/CurrentUserBadge/index.tsx b/src/components/CurrentUserBadge/index.tsx index 05cf747..2a0b391 100644 --- a/src/components/CurrentUserBadge/index.tsx +++ b/src/components/CurrentUserBadge/index.tsx @@ -18,13 +18,13 @@ export const CurrentUserBadge = (props: {}) => { return (
- {formatNumber.format(((account?.lamports || 0) / LAMPORTS_PER_SOL))} SOL + {formatNumber.format((account?.lamports || 0) / LAMPORTS_PER_SOL)} SOL
{shortenAddress(`${wallet.publicKey}`)}
diff --git a/src/components/DepositInfoLine/index.tsx b/src/components/DepositInfoLine/index.tsx index ee9f94f..e282efd 100644 --- a/src/components/DepositInfoLine/index.tsx +++ b/src/components/DepositInfoLine/index.tsx @@ -1,31 +1,45 @@ -import React, { } from "react"; -import { useTokenName, useUserBalance, useCollateralBalance } from './../../hooks'; +import React from "react"; +import { + useTokenName, + useUserBalance, + useCollateralBalance, +} from "./../../hooks"; import { LendingReserve } from "../../models/lending"; import { formatNumber } from "../../utils/utils"; import { Card } from "antd"; -import './style.less'; +import "./style.less"; import { PublicKey } from "@solana/web3.js"; -export const DepositInfoLine = (props: { - className?: string, - reserve: LendingReserve, - address: PublicKey }) => { +export const DepositInfoLine = (props: { + className?: string; + reserve: LendingReserve; + address: PublicKey; +}) => { const name = useTokenName(props.reserve.liquidityMint); const { balance: tokenBalance } = useUserBalance(props.reserve.liquidityMint); const { balance: collateralBalance } = useCollateralBalance(props.reserve); - return -
-
Your balance in Oyster
-
{formatNumber.format(collateralBalance)} {name}
-
-
-
Your wallet balance
-
{formatNumber.format(tokenBalance)} {name}
-
-
-
Health factor
-
--
-
-
-} \ No newline at end of file + return ( + +
+
Your balance in Oyster
+
+ {formatNumber.format(collateralBalance)} {name} +
+
+
+
Your wallet balance
+
+ {formatNumber.format(tokenBalance)} {name} +
+
+
+
Health factor
+
--
+
+
+ ); +}; diff --git a/src/components/DepositInput/index.tsx b/src/components/DepositInput/index.tsx index 06ed29a..4de7604 100644 --- a/src/components/DepositInput/index.tsx +++ b/src/components/DepositInput/index.tsx @@ -1,19 +1,23 @@ import React, { useCallback, useState } from "react"; -import { useTokenName, useUserBalance } from '../../hooks'; +import { useTokenName, useUserBalance } from "../../hooks"; import { LendingReserve } from "../../models/lending"; import { TokenIcon } from "../TokenIcon"; import { Button, Card } from "antd"; import { NumericInput } from "../Input/numeric"; import { useConnection } from "../../contexts/connection"; import { useWallet } from "../../contexts/wallet"; -import { deposit } from '../../actions/deposit'; +import { deposit } from "../../actions/deposit"; import { PublicKey } from "@solana/web3.js"; -import './style.less'; +import "./style.less"; -export const DepositInput = (props: { className?: string, reserve: LendingReserve, address: PublicKey }) => { +export const DepositInput = (props: { + className?: string; + reserve: LendingReserve; + address: PublicKey; +}) => { const connection = useConnection(); const { wallet } = useWallet(); - const [value, setValue] = useState(''); + const [value, setValue] = useState(""); const reserve = props.reserve; const address = props.address; @@ -29,42 +33,57 @@ export const DepositInput = (props: { className?: string, reserve: LendingReserv reserve, address, connection, - wallet); - }, [value, reserve, fromAccounts, address]); + wallet + ); + }, [connection, wallet, value, reserve, fromAccounts, address]); - const bodyStyle: React.CSSProperties = { - display: 'flex', + const bodyStyle: React.CSSProperties = { + display: "flex", flex: 1, - justifyContent: 'center', - alignItems: 'center', - height: '100%', + justifyContent: "center", + alignItems: "center", + height: "100%", }; - return + return ( + +
+
+ How much would you like to deposit? +
+
+ + { + setValue(val); + }} + autoFocus={true} + style={{ + fontSize: 20, + boxShadow: "none", + borderColor: "transparent", + outline: "transpaernt", + }} + placeholder="0.00" + /> +
{name}
+
-
-
- How much would you like to deposit? +
-
- - { - setValue(val); - }} - autoFocus={true} - style={{ - fontSize: 20, - boxShadow: "none", - borderColor: "transparent", - outline: "transpaernt", - }} - placeholder="0.00" - /> -
{name}
-
- - -
- ; -} \ No newline at end of file + + ); +}; diff --git a/src/components/Identicon/index.tsx b/src/components/Identicon/index.tsx index 369488a..39a9a2f 100644 --- a/src/components/Identicon/index.tsx +++ b/src/components/Identicon/index.tsx @@ -10,14 +10,17 @@ export const Identicon = (props: { style?: React.CSSProperties; className?: string; }) => { - const { style, className } = props; - const address = typeof props.address === 'string' ? props.address : props.address?.toBase58(); + const { style, className } = props; + const address = + typeof props.address === "string" + ? props.address + : props.address?.toBase58(); const ref = useRef(); useEffect(() => { if (address && ref.current) { ref.current.innerHTML = ""; - ref.current.className = props.className || ""; + ref.current.className = className || ""; ref.current.appendChild( Jazzicon( style?.width || 16, diff --git a/src/components/Input/numeric.tsx b/src/components/Input/numeric.tsx index fb3cd55..11605a2 100644 --- a/src/components/Input/numeric.tsx +++ b/src/components/Input/numeric.tsx @@ -36,4 +36,4 @@ export class NumericInput extends React.Component { /> ); } -} \ No newline at end of file +} diff --git a/src/components/Layout/index.tsx b/src/components/Layout/index.tsx index d88b6f3..1f5f0d1 100644 --- a/src/components/Layout/index.tsx +++ b/src/components/Layout/index.tsx @@ -1,16 +1,16 @@ import React from "react"; import "./../../App.less"; -import { Menu } from 'antd'; +import { Menu } from "antd"; import { PieChartOutlined, GithubOutlined, BankOutlined, LogoutOutlined, HomeOutlined, - RocketOutlined -} from '@ant-design/icons'; + RocketOutlined, +} from "@ant-design/icons"; -import BasicLayout, { } from '@ant-design/pro-layout'; +import BasicLayout from "@ant-design/pro-layout"; import { AppBar } from "./../AppBar"; import { Link, useLocation } from "react-router-dom"; import { useConnectionConfig } from "../../contexts/connection"; @@ -19,16 +19,17 @@ export const AppLayout = (props: any) => { const { env } = useConnectionConfig(); const location = useLocation(); - console.log(location.pathname) + console.log(location.pathname); const paths: { [key: string]: string } = { - '/dashboard': '2', - '/deposit': '3', - '/borrow': '4', - '/faucet': '4', - + "/dashboard": "2", + "/deposit": "3", + "/borrow": "4", + "/faucet": "4", }; - const current = [...Object.keys(paths)].find(key => location.pathname.startsWith(key)) || ''; + const current = + [...Object.keys(paths)].find((key) => location.pathname.startsWith(key)) || + ""; const defaultKey = paths[current] || "1"; return ( @@ -36,9 +37,10 @@ export const AppLayout = (props: any) => {
Oyster Lending is unaudited software. Use at your own risk. -
+
- { logo={
} rightContentRender={() => } links={[ -
+
+ +
, ]} menuContentRender={() => { - return - }> - - Home - - - } > - - Dashboard - - - }> - - Deposit - - - }> - - Borrow - - - {env !== "mainnet-beta" && }> - - Faucet - - } - + return ( + + }> + + Home + + + }> + + Dashboard + + + }> + + Deposit + + + }> + + Borrow + + + {env !== "mainnet-beta" && ( + }> + + Faucet + + + )} + + ); }} > {props.children}
); -} - +}; diff --git a/src/components/ReserveStatus/index.tsx b/src/components/ReserveStatus/index.tsx index c6b64e4..4594b5c 100644 --- a/src/components/ReserveStatus/index.tsx +++ b/src/components/ReserveStatus/index.tsx @@ -1,26 +1,35 @@ -import React, { useState } from "react"; +import React from "react"; import { LendingReserve } from "../../models/lending"; import { Card } from "antd"; import { PublicKey } from "@solana/web3.js"; -import './style.less'; +import "./style.less"; -export const ReserveStatus = (props: { className?: string, reserve: LendingReserve, address: PublicKey }) => { - const [] = useState(''); - - const bodyStyle: React.CSSProperties = { - display: 'flex', - justifyContent: 'center', - alignItems: 'center' +export const ReserveStatus = (props: { + className?: string; + reserve: LendingReserve; + address: PublicKey; +}) => { + const bodyStyle: React.CSSProperties = { + display: "flex", + justifyContent: "center", + alignItems: "center", }; - return Reserve Status & Configuration - } - bodyStyle={bodyStyle}> - -
- TODO: Reserve Status - add chart -
-
; -} \ No newline at end of file + return ( + Reserve Status & Configuration} + bodyStyle={bodyStyle} + > +
+ TODO: Reserve Status - add chart +
+
+ ); +}; diff --git a/src/components/SideReserveOverview/index.tsx b/src/components/SideReserveOverview/index.tsx index 634f7a1..6dc0b5c 100644 --- a/src/components/SideReserveOverview/index.tsx +++ b/src/components/SideReserveOverview/index.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useTokenName } from './../../hooks'; +import { useTokenName } from "./../../hooks"; import { LendingReserve } from "../../models/lending"; import { TokenIcon } from "../../components/TokenIcon"; import { formatNumber, formatPct, fromLamports } from "../../utils/utils"; @@ -10,22 +10,25 @@ import { PublicKey } from "@solana/web3.js"; const { Text } = Typography; export enum SideReserveOverviewMode { - Deposit = 'deposit', - Borrow = 'borrow' + Deposit = "deposit", + Borrow = "borrow", } export const SideReserveOverview = (props: { className?: string; - reserve: LendingReserve, - address: PublicKey, - mode: SideReserveOverviewMode + reserve: LendingReserve; + address: PublicKey; + mode: SideReserveOverviewMode; }) => { const reserve = props.reserve; const mode = props.mode; const name = useTokenName(reserve?.liquidityMint); const liquidityMint = useMint(props.reserve.liquidityMint); - const totalLiquidity = fromLamports(props.reserve.totalLiquidity.toNumber(), liquidityMint); + const totalLiquidity = fromLamports( + props.reserve.totalLiquidity.toNumber(), + liquidityMint + ); // TODO: calculate const depositApy = 0.048; @@ -38,80 +41,91 @@ export const SideReserveOverview = (props: { let extraInfo: JSX.Element | null = null; if (mode === SideReserveOverviewMode.Deposit) { - - extraInfo = <> -
- - Deposit APY: - -
- {formatPct.format(depositApy)} + extraInfo = ( + <> +
+ + Deposit APY: + +
{formatPct.format(depositApy)}
-
-
- - Maxiumum LTV: - -
- {formatPct.format(maxLTV)} +
+ + Maxiumum LTV: + +
{formatPct.format(maxLTV)}
-
-
- - Liquidation threashold: - -
- {formatPct.format(liquidiationThreshold)} +
+ + Liquidation threashold: + +
+ {formatPct.format(liquidiationThreshold)} +
-
-
- - Liquidation penalty: - -
- {formatPct.format(liquidiationPenalty)} +
+ + Liquidation penalty: + +
+ {formatPct.format(liquidiationPenalty)} +
-
- ; + + ); } else if (mode === SideReserveOverviewMode.Borrow) { - extraInfo = <> -
- - Borrow APY: - -
- {formatPct.format(borrowApy)} -
-
- ; + extraInfo = ( + <> +
+ + Borrow APY: + +
{formatPct.format(borrowApy)}
+
+ + ); } - return - {name} Reserve Overview -
- }> -
- - Utilization rate: + return ( + + {" "} + {name} Reserve Overview +
+ } + > +
+ + Utilization rate: -
- {formatPct.format(utilizationRate)} +
{formatPct.format(utilizationRate)}
-
-
- - Available liquidity: +
+ + Available liquidity: -
- {formatNumber.format(totalLiquidity)} {name} +
+ {formatNumber.format(totalLiquidity)} {name} +
-
- {extraInfo} - ; -} \ No newline at end of file + {extraInfo} + + ); +}; diff --git a/src/components/TokenIcon/index.tsx b/src/components/TokenIcon/index.tsx index 248dfef..7ad7507 100644 --- a/src/components/TokenIcon/index.tsx +++ b/src/components/TokenIcon/index.tsx @@ -18,8 +18,8 @@ export const TokenIcon = (props: { alt="Token icon" className={props.className} key={icon} - width={props.style?.width || '20'} - height={props.style?.height || '20'} + width={props.style?.width || "20"} + height={props.style?.height || "20"} src={icon} style={{ marginRight: "0.5rem", diff --git a/src/components/UserLendingCard/index.tsx b/src/components/UserLendingCard/index.tsx index 8d3ede8..0803664 100644 --- a/src/components/UserLendingCard/index.tsx +++ b/src/components/UserLendingCard/index.tsx @@ -1,18 +1,21 @@ import React from "react"; -import { useCollateralBalance, useTokenName, useUserBalance } from './../../hooks'; +import { + useCollateralBalance, + useTokenName, + useUserBalance, +} from "./../../hooks"; import { LendingReserve } from "../../models/lending"; import { formatNumber } from "../../utils/utils"; import { Button, Card, Typography } from "antd"; import { Link } from "react-router-dom"; -import { useMint } from "../../contexts/accounts"; import { PublicKey } from "@solana/web3.js"; const { Text } = Typography; export const UserLendingCard = (props: { className?: string; - reserve: LendingReserve, - address: PublicKey, + reserve: LendingReserve; + address: PublicKey; }) => { const reserve = props.reserve; const address = props.address; @@ -22,92 +25,99 @@ export const UserLendingCard = (props: { const { balance: tokenBalance } = useUserBalance(props.reserve.liquidityMint); const { balance: collateralBalance } = useCollateralBalance(props.reserve); - // TODO: calculate const borrowed = 0; - const healthFactor = '--'; + const healthFactor = "--"; const ltv = 0; const available = 0; + return ( + + Your Information +
+ } + > +

Borrows

- return - Your Information -
- }> -

Borrows

- -
- - Borrowed +
+ + Borrowed -
- {formatNumber.format(borrowed)} {name} +
+ {formatNumber.format(borrowed)} {name} +
-
-
- - Health factor: +
+ + Health factor: -
- {healthFactor} +
{healthFactor}
-
-
- - Loan to value: +
+ + Loan to value: -
- {formatNumber.format(ltv)} +
{formatNumber.format(ltv)}
-
-
- - Available to you: +
+ + Available to you: -
- {formatNumber.format(available)} {name} +
+ {formatNumber.format(available)} {name} +
-
-

Deposits

+

Deposits

-
- - Wallet balance: +
+ + Wallet balance: -
- {formatNumber.format(tokenBalance)} {name} +
+ {formatNumber.format(tokenBalance)} {name} +
-
-
- - You already deposited: +
+ + You already deposited: -
- {formatNumber.format(collateralBalance)} {name} +
+ {formatNumber.format(collateralBalance)} {name} +
-
-
- - - - - - - - - - - - -
- - - ; -} \ No newline at end of file +
+ + + + + + + + + + + + +
+ + ); +}; diff --git a/src/components/WithdrawInput/index.tsx b/src/components/WithdrawInput/index.tsx index 0012870..2e28cb1 100644 --- a/src/components/WithdrawInput/index.tsx +++ b/src/components/WithdrawInput/index.tsx @@ -1,77 +1,110 @@ import React, { useCallback, useState } from "react"; -import { useCollateralBalance, useTokenName, useUserBalance } from '../../hooks'; +import { + useCollateralBalance, + useTokenName, + useUserBalance, +} from "../../hooks"; import { LendingReserve } from "../../models/lending"; import { TokenIcon } from "../TokenIcon"; import { Button, Card } from "antd"; import { NumericInput } from "../Input/numeric"; import { useConnection } from "../../contexts/connection"; import { useWallet } from "../../contexts/wallet"; -import { withdraw } from '../../actions'; +import { withdraw } from "../../actions"; import { PublicKey } from "@solana/web3.js"; -import './style.less'; -import { useMint } from "../../contexts/accounts"; +import "./style.less"; -export const WithdrawInput = (props: { className?: string, reserve: LendingReserve, address: PublicKey }) => { +export const WithdrawInput = (props: { + className?: string; + reserve: LendingReserve; + address: PublicKey; +}) => { const connection = useConnection(); const { wallet } = useWallet(); - const [value, setValue] = useState(''); + const [value, setValue] = useState(""); const reserve = props.reserve; const address = props.address; - const liquidityMint = useMint(reserve?.liquidityMint); const name = useTokenName(reserve?.liquidityMint); - const { balanceLamports: collateralBalanceLamports, accounts: fromAccounts } = useUserBalance(reserve?.collateralMint); - const { - balance: collateralBalanceInLiquidity - } = useCollateralBalance(reserve); + const { + balanceLamports: collateralBalanceLamports, + accounts: fromAccounts, + } = useUserBalance(reserve?.collateralMint); + const { balance: collateralBalanceInLiquidity } = useCollateralBalance( + reserve + ); const onWithdraw = useCallback(() => { withdraw( fromAccounts[0], Math.ceil( - collateralBalanceLamports * - (parseFloat(value) / collateralBalanceInLiquidity) + collateralBalanceLamports * + (parseFloat(value) / collateralBalanceInLiquidity) ), reserve, address, connection, - wallet); - }, [value, reserve, fromAccounts, address, liquidityMint]); + wallet + ); + }, [ + connection, + wallet, + collateralBalanceLamports, + collateralBalanceInLiquidity, + value, + reserve, + fromAccounts, + address, + ]); - const bodyStyle: React.CSSProperties = { - display: 'flex', + const bodyStyle: React.CSSProperties = { + display: "flex", flex: 1, - justifyContent: 'center', - alignItems: 'center', - height: '100%', + justifyContent: "center", + alignItems: "center", + height: "100%", }; - return + return ( + +
+
+ How much would you like to withdraw? +
+
+ + { + setValue(val); + }} + autoFocus={true} + style={{ + fontSize: 20, + boxShadow: "none", + borderColor: "transparent", + outline: "transpaernt", + }} + placeholder="0.00" + /> +
{name}
+
-
-
- How much would you like to withdraw? +
-
- - { - setValue(val); - }} - autoFocus={true} - style={{ - fontSize: 20, - boxShadow: "none", - borderColor: "transparent", - outline: "transpaernt", - }} - placeholder="0.00" - /> -
{name}
-
- - -
- ; -} \ No newline at end of file + + ); +}; diff --git a/src/constants/ids.tsx b/src/constants/ids.tsx index ed4d14b..0f37eb9 100644 --- a/src/constants/ids.tsx +++ b/src/constants/ids.tsx @@ -12,7 +12,7 @@ export let LENDING_PROGRAM_ID = new PublicKey( ); export const setProgramIds = (envName: string) => { - // Add dynamic program ids + // Add dynamic program ids }; export const programIds = () => { diff --git a/src/contexts/accounts.tsx b/src/contexts/accounts.tsx index f897023..da037e0 100644 --- a/src/contexts/accounts.tsx +++ b/src/contexts/accounts.tsx @@ -3,7 +3,7 @@ import { useConnection } from "./connection"; import { useWallet } from "./wallet"; import { AccountInfo, Connection, PublicKey } from "@solana/web3.js"; import { programIds, WRAPPED_SOL_MINT } from "./../constants/ids"; -import { AccountLayout, u64, MintInfo, MintLayout, Token } from "@solana/spl-token"; +import { AccountLayout, u64, MintInfo, MintLayout } from "@solana/spl-token"; import { TokenAccount } from "./../models"; import { chunks } from "./../utils/utils"; import { EventEmitter } from "./../utils/eventEmitter"; @@ -46,7 +46,10 @@ export const MintParser = (pubKey: PublicKey, info: AccountInfo) => { return details; }; -export const TokenAccountParser = (pubKey: PublicKey, info: AccountInfo) => { +export const TokenAccountParser = ( + pubKey: PublicKey, + info: AccountInfo +) => { const buffer = Buffer.from(info.data); const data = deserializeAccount(buffer); @@ -118,8 +121,12 @@ export const cache = { return query; }, - add: (id: PublicKey | string, obj: AccountInfo, parser?: AccountParser) => { - const address = typeof id === 'string' ? id : id?.toBase58(); + add: ( + id: PublicKey | string, + obj: AccountInfo, + parser?: AccountParser + ) => { + const address = typeof id === "string" ? id : id?.toBase58(); const deserialize = parser ? parser : keyToAccountParser.get(address); if (!deserialize) { throw new Error( @@ -160,7 +167,7 @@ export const cache = { }, registerParser: (pubkey: PublicKey | string, parser: AccountParser) => { if (pubkey) { - const address = typeof pubkey === 'string' ? pubkey : pubkey?.toBase58(); + const address = typeof pubkey === "string" ? pubkey : pubkey?.toBase58(); keyToAccountParser.set(address, parser); } @@ -172,7 +179,7 @@ export const useAccountsContext = () => { const context = useContext(AccountsContext); return context; -} +}; function wrapNativeAccount( pubkey: PublicKey, @@ -206,13 +213,16 @@ const UseNativeAccount = () => { const [nativeAccount, setNativeAccount] = useState>(); - const updateCache = useCallback((account) => { - const wrapped = wrapNativeAccount(wallet.publicKey, account); - if (wrapped !== undefined && wallet) { - cache.registerParser(wallet.publicKey.toBase58(), TokenAccountParser); - genericCache.set(wallet.publicKey.toBase58(), wrapped as TokenAccount); - } - }, [wallet]); + const updateCache = useCallback( + (account) => { + const wrapped = wrapNativeAccount(wallet.publicKey, account); + if (wrapped !== undefined && wallet) { + cache.registerParser(wallet.publicKey?.toBase58(), TokenAccountParser); + genericCache.set(wallet.publicKey?.toBase58(), wrapped as TokenAccount); + } + }, + [wallet] + ); useEffect(() => { if (!connection || !wallet?.publicKey) { @@ -231,7 +241,7 @@ const UseNativeAccount = () => { setNativeAccount(acc); } }); - }, [setNativeAccount, wallet, wallet.publicKey, connection]); + }, [setNativeAccount, wallet, wallet.publicKey, connection, updateCache]); return { nativeAccount }; }; @@ -252,10 +262,9 @@ const precacheUserTokenAccounts = async ( const accounts = await connection.getTokenAccountsByOwner(owner, { programId: programIds().token, }); - accounts.value - .forEach((info) => { - cache.add(info.pubkey.toBase58(), info.account, TokenAccountParser); - }); + accounts.value.forEach((info) => { + cache.add(info.pubkey.toBase58(), info.account, TokenAccountParser); + }); }; export function AccountsProvider({ children = null as any }) { @@ -266,15 +275,21 @@ export function AccountsProvider({ children = null as any }) { const { nativeAccount } = UseNativeAccount(); const selectUserAccounts = useCallback(() => { - return cache.byParser(TokenAccountParser).map(id => cache.get(id)).filter( - (a) => a && a.info.owner.toBase58() === wallet.publicKey.toBase58() - ).map(a => a as TokenAccount); + return cache + .byParser(TokenAccountParser) + .map((id) => cache.get(id)) + .filter( + (a) => a && a.info.owner.toBase58() === wallet.publicKey?.toBase58() + ) + .map((a) => a as TokenAccount); }, [wallet]); useEffect(() => { - const accounts = selectUserAccounts().filter((a) => a !== undefined) as TokenAccount[]; + const accounts = selectUserAccounts().filter( + (a) => a !== undefined + ) as TokenAccount[]; setUserAccounts(accounts); - }, [nativeAccount, wallet, tokenAccounts]); + }, [nativeAccount, wallet, tokenAccounts, selectUserAccounts]); const publicKey = wallet?.publicKey; useEffect(() => { @@ -296,10 +311,7 @@ export function AccountsProvider({ children = null as any }) { if (info.accountInfo.data.length === AccountLayout.span) { const data = deserializeAccount(info.accountInfo.data); - if ( - PRECACHED_OWNERS.has(data.owner.toBase58()) || - !cache.get(id) - ) { + if (PRECACHED_OWNERS.has(data.owner.toBase58()) || !cache.get(id)) { cache.add(id, info.accountInfo, TokenAccountParser); setTokenAccounts(selectUserAccounts()); accountEmitter.raiseAccountUpdated(id); @@ -359,18 +371,20 @@ export const getMultipleAccounts = async ( const array = result .map( (a) => - a.array.map((acc) => { - if (!acc) { - return; - } + a.array + .map((acc) => { + if (!acc) { + return; + } - const { data, ...rest } = acc; - const obj = { - ...rest, - data: Buffer.from(data[0], "base64"), - } as AccountInfo; - return obj; - }).filter(_ => _) as AccountInfo[] + const { data, ...rest } = acc; + const obj = { + ...rest, + data: Buffer.from(data[0], "base64"), + } as AccountInfo; + return obj; + }) + .filter((_) => _) as AccountInfo[] ) .flat(); return { keys, array }; @@ -412,15 +426,15 @@ export function useMint(key?: string | PublicKey) { cache .query(connection, id, MintParser) - .then(acc => setMint(acc.info as any)) - .catch((err) => - console.log(err) - ); + .then((acc) => setMint(acc.info as any)) + .catch((err) => console.log(err)); const dispose = cache.emitter.onCache((e) => { const event = e; if (event.id === id) { - cache.query(connection, id, MintParser).then(mint => setMint(mint.info as any)); + cache + .query(connection, id, MintParser) + .then((mint) => setMint(mint.info as any)); } }); return () => { @@ -443,9 +457,9 @@ export function useAccount(pubKey?: PublicKey) { return; } - const acc = await cache.query(connection, key, TokenAccountParser).catch((err) => - console.log(err) - ); + const acc = await cache + .query(connection, key, TokenAccountParser) + .catch((err) => console.log(err)); if (acc) { setAccount(acc); } diff --git a/src/contexts/connection.tsx b/src/contexts/connection.tsx index 88e46b0..8778473 100644 --- a/src/contexts/connection.tsx +++ b/src/contexts/connection.tsx @@ -10,13 +10,18 @@ import React, { useContext, useEffect, useMemo, useState } from "react"; import { setProgramIds } from "./../constants/ids"; import { notify } from "./../utils/notifications"; import { ExplorerLink } from "../components/ExplorerLink"; -import LocalTokens from '../config/tokens.json'; +import LocalTokens from "../config/tokens.json"; -export type ENV = "mainnet-beta" | "testnet" | "devnet" | "localnet" | "lending"; +export type ENV = + | "mainnet-beta" + | "testnet" + | "devnet" + | "localnet" + | "lending"; export const ENDPOINTS = [ { - name: 'lending' as ENV, + name: "lending" as ENV, endpoint: "https://tln.solana.com", }, { @@ -88,7 +93,7 @@ export function ConnectionProvider({ children = undefined as any }) { .then((res) => { return res.json(); }) - .catch(err => []) + .catch((err) => []) .then((list: KnownToken[]) => { const knownMints = [...LocalTokens, ...list].reduce((map, item) => { map.set(item.mintAddress, item); diff --git a/src/contexts/lending.tsx b/src/contexts/lending.tsx index bcf354d..28bf96c 100644 --- a/src/contexts/lending.tsx +++ b/src/contexts/lending.tsx @@ -1,14 +1,23 @@ import React, { useCallback, useEffect, useState } from "react"; import { useConnection } from "./connection"; import { LENDING_PROGRAM_ID } from "./../constants/ids"; -import { LendingMarketParser, isLendingReserve, isLendingMarket, LendingReserveParser, LendingReserve } from "./../models/lending"; -import { cache, getMultipleAccounts, MintParser, ParsedAccount } from "./accounts"; +import { + LendingMarketParser, + isLendingReserve, + isLendingMarket, + LendingReserveParser, + LendingReserve, +} from "./../models/lending"; +import { + cache, + getMultipleAccounts, + MintParser, + ParsedAccount, +} from "./accounts"; import { PublicKey } from "@solana/web3.js"; import { DexMarketParser } from "../models/dex"; -export interface LendingContextState { - -} +export interface LendingContextState {} const LendingContext = React.createContext(null); @@ -17,14 +26,13 @@ export function LendingProvider({ children = null as any }) { return ( {children} ); -}; - +} export const useLending = () => { const connection = useConnection(); @@ -32,9 +40,17 @@ export const useLending = () => { const processAccount = useCallback((item) => { if (isLendingReserve(item.account)) { - return cache.add(item.pubkey.toBase58(), item.account, LendingReserveParser); + return cache.add( + item.pubkey.toBase58(), + item.account, + LendingReserveParser + ); } else if (isLendingMarket(item.account)) { - return cache.add(item.pubkey.toBase58(), item.account, LendingMarketParser); + return cache.add( + item.pubkey.toBase58(), + item.account, + LendingMarketParser + ); } }, []); @@ -45,20 +61,32 @@ export const useLending = () => { const queryLendingAccounts = async () => { const accounts = (await connection.getProgramAccounts(LENDING_PROGRAM_ID)) .map(processAccount) - .filter(item => item !== undefined); + .filter((item) => item !== undefined); const toQuery = [ - ...accounts.filter(acc => (acc?.info as LendingReserve).lendingMarket !== undefined) - .map(acc => acc as ParsedAccount) - .map(acc => { - const result = [ - cache.registerParser(acc?.info.collateralMint.toBase58(), MintParser), - cache.registerParser(acc?.info.liquidityMint.toBase58(), MintParser), - // ignore dex if its not set - cache.registerParser(acc?.info.dexMarketOption ? acc?.info.dexMarket.toBase58() : '', DexMarketParser), - ].filter(_ => _); - return result; - }) + ...accounts + .filter( + (acc) => (acc?.info as LendingReserve).lendingMarket !== undefined + ) + .map((acc) => acc as ParsedAccount) + .map((acc) => { + const result = [ + cache.registerParser( + acc?.info.collateralMint.toBase58(), + MintParser + ), + cache.registerParser( + acc?.info.liquidityMint.toBase58(), + MintParser + ), + // ignore dex if its not set + cache.registerParser( + acc?.info.dexMarketOption ? acc?.info.dexMarket.toBase58() : "", + DexMarketParser + ), + ].filter((_) => _); + return result; + }), ].flat() as string[]; // This will pre-cache all accounts used by pools @@ -76,12 +104,10 @@ export const useLending = () => { return accounts; }; - Promise.all([ - queryLendingAccounts(), - ]).then((all) => { + Promise.all([queryLendingAccounts()]).then((all) => { setLendingAccounts(all.flat()); }); - }, [connection]); + }, [connection, processAccount]); useEffect(() => { const subID = connection.onProgramAccountChange( @@ -100,7 +126,7 @@ export const useLending = () => { return () => { connection.removeProgramAccountChangeListener(subID); }; - }, [connection, lendingAccounts]); + }, [connection, lendingAccounts, processAccount]); return { accounts: lendingAccounts }; }; diff --git a/src/contexts/market.tsx b/src/contexts/market.tsx index 4237266..31cd01f 100644 --- a/src/contexts/market.tsx +++ b/src/contexts/market.tsx @@ -1,13 +1,8 @@ import React, { useCallback, useContext, useEffect, useState } from "react"; import { MINT_TO_MARKET } from "./../models/marketOverrides"; -import { - STABLE_COINS, -} from "./../utils/utils"; +import { STABLE_COINS } from "./../utils/utils"; import { useConnectionConfig } from "./connection"; -import { - cache, - getMultipleAccounts, -} from "./accounts"; +import { cache, getMultipleAccounts } from "./accounts"; import { Market, MARKETS, Orderbook, TOKEN_MINTS } from "@project-serum/serum"; import { AccountInfo, Connection, PublicKey } from "@solana/web3.js"; import { useMemo } from "react"; @@ -39,14 +34,10 @@ export function MarketProvider({ children = null as any }) { ]); // TODO: identify which markets to query ... - const mints = useMemo(() => [ - - ] as PublicKey[], []); + const mints = useMemo(() => [] as PublicKey[], []); const marketByMint = useMemo(() => { - return [ - ...new Set(mints).values(), - ].reduce((acc, key) => { + return [...new Set(mints).values()].reduce((acc, key) => { const mintAddress = key.toBase58(); const SERUM_TOKEN = TOKEN_MINTS.find( @@ -240,8 +231,6 @@ export const useMidPriceInUSD = (mint: string) => { return { price, isBase: price === 1.0 }; }; - - const getMidPrice = (marketAddress?: string, mintAddress?: string) => { const SERUM_TOKEN = TOKEN_MINTS.find( (a) => a.address.toBase58() === mintAddress diff --git a/src/hooks/index.ts b/src/hooks/index.ts index 089e0b0..df1aa6f 100644 --- a/src/hooks/index.ts +++ b/src/hooks/index.ts @@ -1,6 +1,6 @@ -export * from './useUserAccounts'; -export * from './useAccountByMint'; -export * from './useLendingReserves'; -export * from './useTokenName'; -export * from './useUserBalance'; -export * from './useCollateralBalance'; +export * from "./useUserAccounts"; +export * from "./useAccountByMint"; +export * from "./useLendingReserves"; +export * from "./useTokenName"; +export * from "./useUserBalance"; +export * from "./useCollateralBalance"; diff --git a/src/hooks/useAccountByMint.ts b/src/hooks/useAccountByMint.ts index 5ee1269..b508440 100644 --- a/src/hooks/useAccountByMint.ts +++ b/src/hooks/useAccountByMint.ts @@ -1,4 +1,4 @@ -import { useUserAccounts } from './useUserAccounts'; +import { useUserAccounts } from "./useUserAccounts"; export const useAccountByMint = (mint: string) => { const { userAccounts } = useUserAccounts(); diff --git a/src/hooks/useCollateralBalance.ts b/src/hooks/useCollateralBalance.ts index 42fb550..223a43b 100644 --- a/src/hooks/useCollateralBalance.ts +++ b/src/hooks/useCollateralBalance.ts @@ -14,6 +14,6 @@ export function useCollateralBalance(reserve?: LendingReserve) { return { balance: fromLamports(collateralRatioLamports, mint), balanceLamports: collateralRatioLamports, - accounts + accounts, }; -} \ No newline at end of file +} diff --git a/src/hooks/useLendingReserves.ts b/src/hooks/useLendingReserves.ts index 9372681..c9ab926 100644 --- a/src/hooks/useLendingReserves.ts +++ b/src/hooks/useLendingReserves.ts @@ -1,14 +1,19 @@ import { PublicKey } from "@solana/web3.js"; import { useEffect, useState } from "react"; import { LendingReserve, LendingReserveParser } from "../models/lending"; -import { cache, ParsedAccount } from './../contexts/accounts'; +import { cache, ParsedAccount } from "./../contexts/accounts"; const getLendingReserves = () => { - return cache.byParser(LendingReserveParser).map(id => cache.get(id)).filter(acc => acc !== undefined) as any[]; + return cache + .byParser(LendingReserveParser) + .map((id) => cache.get(id)) + .filter((acc) => acc !== undefined) as any[]; }; export function useLendingReserves() { - const [reserveAccounts, setReserveAccounts] = useState[]>([]); + const [reserveAccounts, setReserveAccounts] = useState< + ParsedAccount[] + >([]); useEffect(() => { setReserveAccounts(getLendingReserves()); @@ -22,7 +27,7 @@ export function useLendingReserves() { return () => { dispose(); }; - }, [setReserveAccounts]) + }, [setReserveAccounts]); return { reserveAccounts, @@ -30,8 +35,10 @@ export function useLendingReserves() { } export function useLendingReserve(address: string | PublicKey) { - const id = typeof address === 'string' ? address : address?.toBase58(); - const [reserveAccount, setReserveAccount] = useState>(); + const id = typeof address === "string" ? address : address?.toBase58(); + const [reserveAccount, setReserveAccount] = useState< + ParsedAccount + >(); useEffect(() => { setReserveAccount(cache.get(id)); @@ -45,7 +52,7 @@ export function useLendingReserve(address: string | PublicKey) { return () => { dispose(); }; - }, [setReserveAccount]) + }, [id, setReserveAccount]); return reserveAccount; -} \ No newline at end of file +} diff --git a/src/hooks/useTokenName.ts b/src/hooks/useTokenName.ts index 4d2ee8d..167f193 100644 --- a/src/hooks/useTokenName.ts +++ b/src/hooks/useTokenName.ts @@ -4,6 +4,7 @@ import { getTokenName } from "../utils/utils"; export function useTokenName(mintAddress?: string | PublicKey) { const { tokenMap } = useConnectionConfig(); - const address = typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58(); + const address = + typeof mintAddress === "string" ? mintAddress : mintAddress?.toBase58(); return getTokenName(tokenMap, address); -} \ No newline at end of file +} diff --git a/src/hooks/useUserAccounts.ts b/src/hooks/useUserAccounts.ts index 38fe752..753565f 100644 --- a/src/hooks/useUserAccounts.ts +++ b/src/hooks/useUserAccounts.ts @@ -1,9 +1,9 @@ import { TokenAccount } from "../models"; -import { useAccountsContext } from './../contexts/accounts'; +import { useAccountsContext } from "./../contexts/accounts"; export function useUserAccounts() { - const context = useAccountsContext(); - return { - userAccounts: context.userAccounts as TokenAccount[], - }; - } \ No newline at end of file + const context = useAccountsContext(); + return { + userAccounts: context.userAccounts as TokenAccount[], + }; +} diff --git a/src/hooks/useUserBalance.ts b/src/hooks/useUserBalance.ts index ed4d43f..caabab9 100644 --- a/src/hooks/useUserBalance.ts +++ b/src/hooks/useUserBalance.ts @@ -9,18 +9,20 @@ export function useUserBalance(mint?: PublicKey) { const mintInfo = useMint(mint); const accounts = useMemo(() => { return userAccounts - .filter(acc => mint?.equals(acc.info.mint)) + .filter((acc) => mint?.equals(acc.info.mint)) .sort((a, b) => b.info.amount.sub(a.info.amount).toNumber()); }, [userAccounts, mint]); const balanceLamports = useMemo(() => { - return accounts - .reduce((res, item) => res += item.info.amount.toNumber(), 0); - },[accounts]); + return accounts.reduce( + (res, item) => (res += item.info.amount.toNumber()), + 0 + ); + }, [accounts]); return { balance: fromLamports(balanceLamports, mintInfo), balanceLamports, accounts, }; -} \ No newline at end of file +} diff --git a/src/models/dex/index.ts b/src/models/dex/index.ts index fab1886..674239a 100644 --- a/src/models/dex/index.ts +++ b/src/models/dex/index.ts @@ -1 +1 @@ -export * from "./market"; \ No newline at end of file +export * from "./market"; diff --git a/src/models/dex/market.ts b/src/models/dex/market.ts index bf9952e..5e96aa0 100644 --- a/src/models/dex/market.ts +++ b/src/models/dex/market.ts @@ -20,12 +20,18 @@ export const OrderBookParser = (id: PublicKey, acc: AccountInfo) => { return details; }; -const DEFAULT_DEX_ID = new PublicKey('EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o'); +const DEFAULT_DEX_ID = new PublicKey( + "EUqojwWA2rd19FZrzeBncJsm38Jm1hEhE3zsmX3bRc2o" +); -export const DexMarketParser = (pubkey: PublicKey, acc: AccountInfo) => { - const market = MARKETS.find(m => m.address.equals(pubkey)); - const decoded = Market.getLayout(market?.programId || DEFAULT_DEX_ID) - .decode(acc.data); +export const DexMarketParser = ( + pubkey: PublicKey, + acc: AccountInfo +) => { + const market = MARKETS.find((m) => m.address.equals(pubkey)); + const decoded = Market.getLayout(market?.programId || DEFAULT_DEX_ID).decode( + acc.data + ); const details = { pubkey, @@ -41,4 +47,4 @@ export const DexMarketParser = (pubkey: PublicKey, acc: AccountInfo) => cache.registerParser(details.info.asks, OrderBookParser); return details; -} \ No newline at end of file +}; diff --git a/src/models/index.ts b/src/models/index.ts index e105516..f9259dc 100644 --- a/src/models/index.ts +++ b/src/models/index.ts @@ -1,2 +1,2 @@ export * from "./account"; -export * from './lending'; +export * from "./lending"; diff --git a/src/models/lending/borrow.ts b/src/models/lending/borrow.ts index 46999cd..9708007 100644 --- a/src/models/lending/borrow.ts +++ b/src/models/lending/borrow.ts @@ -8,7 +8,7 @@ import BN from "bn.js"; import * as BufferLayout from "buffer-layout"; import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids"; import * as Layout from "./../../utils/layout"; -import { LendingInstruction } from './lending'; +import { LendingInstruction } from "./lending"; /// Borrow tokens from a reserve by depositing collateral tokens. The number of borrowed tokens /// is calculated by market price. The debt obligation is tokenized. @@ -49,7 +49,7 @@ export const borrowInstruction = ( dexMarket: PublicKey, dexOrderBookSide: PublicKey, - memory: PublicKey, + memory: PublicKey ): TransactionInstruction => { const dataLayout = BufferLayout.struct([ BufferLayout.u8("instruction"), @@ -59,7 +59,7 @@ export const borrowInstruction = ( const data = Buffer.alloc(dataLayout.span); dataLayout.encode( { - instruction: LendingInstruction.BorrowReserveLiquidity, + instruction: LendingInstruction.BorrowReserveLiquidity, collateralAmount: new BN(collateralAmount), }, data @@ -69,9 +69,17 @@ export const borrowInstruction = ( { pubkey: from, isSigner: false, isWritable: true }, { pubkey: to, isSigner: false, isWritable: true }, { pubkey: depositReserve, isSigner: false, isWritable: true }, - { pubkey: depositReserveCollateralSupply, isSigner: false, isWritable: true }, + { + pubkey: depositReserveCollateralSupply, + isSigner: false, + isWritable: true, + }, { pubkey: borrowReserve, isSigner: false, isWritable: true }, - { pubkey: borrowReserveLiquiditySupply, isSigner: false, isWritable: false }, + { + pubkey: borrowReserveLiquiditySupply, + isSigner: false, + isWritable: false, + }, { pubkey: obligation, isSigner: false, isWritable: true }, { pubkey: obligationMint, isSigner: false, isWritable: true }, { pubkey: obligationTokenOutput, isSigner: false, isWritable: true }, diff --git a/src/models/lending/index.ts b/src/models/lending/index.ts index 0dd4c6e..6da1134 100644 --- a/src/models/lending/index.ts +++ b/src/models/lending/index.ts @@ -1,5 +1,5 @@ -export * from './market'; -export * from './reserve'; -export * from './obligation'; -export * from './lending'; -export * from './borrow'; +export * from "./market"; +export * from "./reserve"; +export * from "./obligation"; +export * from "./lending"; +export * from "./borrow"; diff --git a/src/models/lending/lending.ts b/src/models/lending/lending.ts index 6b281e1..030bdf2 100644 --- a/src/models/lending/lending.ts +++ b/src/models/lending/lending.ts @@ -4,5 +4,5 @@ export enum LendingInstruction { DepositReserveLiquidity = 2, WithdrawReserveLiquidity = 3, BorrowReserveLiquidity = 4, - RepayReserveLiquidity = 5 -} \ No newline at end of file + RepayReserveLiquidity = 5, +} diff --git a/src/models/lending/market.ts b/src/models/lending/market.ts index 2095fbd..247fa66 100644 --- a/src/models/lending/market.ts +++ b/src/models/lending/market.ts @@ -1,15 +1,9 @@ -import { - AccountInfo, - PublicKey, -} from "@solana/web3.js"; +import { AccountInfo, PublicKey } from "@solana/web3.js"; import * as BufferLayout from "buffer-layout"; import * as Layout from "./../../utils/layout"; export const LendingMarketLayout: typeof BufferLayout.Structure = BufferLayout.struct( - [ - BufferLayout.u8("isInitialized"), - Layout.publicKey("quoteMint"), - ] + [BufferLayout.u8("isInitialized"), Layout.publicKey("quoteMint")] ); export interface LendingMarket { @@ -19,9 +13,12 @@ export interface LendingMarket { export const isLendingMarket = (info: AccountInfo) => { return info.data.length === LendingMarketLayout.span; -} +}; -export const LendingMarketParser = (pubKey: PublicKey, info: AccountInfo) => { +export const LendingMarketParser = ( + pubKey: PublicKey, + info: AccountInfo +) => { const buffer = Buffer.from(info.data); const data = LendingMarketLayout.decode(buffer); @@ -36,6 +33,5 @@ export const LendingMarketParser = (pubKey: PublicKey, info: AccountInfo return details; }; - // TODO: -// create instructions for init \ No newline at end of file +// create instructions for init diff --git a/src/models/lending/obligation.ts b/src/models/lending/obligation.ts index 07e57f0..d5983ad 100644 --- a/src/models/lending/obligation.ts +++ b/src/models/lending/obligation.ts @@ -1,26 +1,24 @@ -import { - PublicKey, -} from "@solana/web3.js"; +import { PublicKey } from "@solana/web3.js"; import BN from "bn.js"; import * as BufferLayout from "buffer-layout"; import * as Layout from "./../../utils/layout"; export const LendingObligationLayout: typeof BufferLayout.Structure = BufferLayout.struct( [ - /// Slot when obligation was updated. Used for calculating interest. - Layout.uint64("lastUpdateSlot"), - /// Amount of collateral tokens deposited for this obligation - Layout.uint64("collateralAmount"), - /// Reserve which collateral tokens were deposited into - Layout.publicKey("collateralSupply"), - /// Borrow rate used for calculating interest. - Layout.uint128("cumulativeBorrowRate"), - /// Amount of tokens borrowed for this obligation plus interest - Layout.uint128("borrowAmount"), - /// Reserve which tokens were borrowed from - Layout.publicKey("borrowReserve"), - /// Mint address of the tokens for this obligation - Layout.publicKey("tokenMint"), + /// Slot when obligation was updated. Used for calculating interest. + Layout.uint64("lastUpdateSlot"), + /// Amount of collateral tokens deposited for this obligation + Layout.uint64("collateralAmount"), + /// Reserve which collateral tokens were deposited into + Layout.publicKey("collateralSupply"), + /// Borrow rate used for calculating interest. + Layout.uint128("cumulativeBorrowRate"), + /// Amount of tokens borrowed for this obligation plus interest + Layout.uint128("borrowAmount"), + /// Reserve which tokens were borrowed from + Layout.publicKey("borrowReserve"), + /// Mint address of the tokens for this obligation + Layout.publicKey("tokenMint"), ] ); @@ -32,4 +30,4 @@ export interface LendingObligation { borrowAmount: BN; // decimals borrowReserve: PublicKey; tokenMint: PublicKey; -} \ No newline at end of file +} diff --git a/src/models/lending/reserve.ts b/src/models/lending/reserve.ts index 023d5fb..416902a 100644 --- a/src/models/lending/reserve.ts +++ b/src/models/lending/reserve.ts @@ -9,7 +9,7 @@ import BN from "bn.js"; import * as BufferLayout from "buffer-layout"; import { LENDING_PROGRAM_ID, TOKEN_PROGRAM_ID } from "../../constants/ids"; import * as Layout from "./../../utils/layout"; -import { LendingInstruction } from './lending'; +import { LendingInstruction } from "./lending"; export const LendingReserveLayout: typeof BufferLayout.Structure = BufferLayout.struct( [ @@ -21,19 +21,22 @@ export const LendingReserveLayout: typeof BufferLayout.Structure = BufferLayout. Layout.publicKey("collateralMint"), Layout.publicKey("collateralSupply"), // TODO: replace u32 option with generic quivalent - BufferLayout.u32('dexMarketOption'), + BufferLayout.u32("dexMarketOption"), Layout.publicKey("dexMarket"), - BufferLayout.struct([ - /// Max utilization rate as a percent - BufferLayout.u8("maxUtilizationRate"), - /// 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"), - ], "config"), + BufferLayout.struct( + [ + /// Max utilization rate as a percent + BufferLayout.u8("maxUtilizationRate"), + /// 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"), + ], + "config" + ), Layout.uint128("cumulativeBorrowRate"), Layout.uint128("totalBorrows"), @@ -47,7 +50,7 @@ export const isLendingReserve = (info: AccountInfo) => { console.log(LendingReserveLayout.span); console.log(info.data.length); return info.data.length === LendingReserveLayout.span; -} +}; export interface LendingReserve { lastUpdateSlot: BN; @@ -63,11 +66,11 @@ export interface LendingReserve { dexMarketPrice: BN; // what is precision on the price? config: { - maxUtilizationRate: number, - loanToValueRatio: number, - liquidationBonus: number, - liquidationThreshold: number, - } + maxUtilizationRate: number; + loanToValueRatio: number; + liquidationBonus: number; + liquidationThreshold: number; + }; // collateralFactor: number; cumulativeBorrowRate: BN; @@ -80,7 +83,10 @@ export interface LendingReserve { // Layout.uint128("total_borrows"), } -export const LendingReserveParser = (pubKey: PublicKey, info: AccountInfo) => { +export const LendingReserveParser = ( + pubKey: PublicKey, + info: AccountInfo +) => { const buffer = Buffer.from(info.data); const data = LendingReserveLayout.decode(buffer); @@ -110,12 +116,12 @@ export const initReserveInstruction = ( lendingMarket: PublicKey, lendingMarketAuthority: PublicKey, - dexMarket: PublicKey, // TODO: optional + dexMarket: PublicKey // TODO: optional ): TransactionInstruction => { const dataLayout = BufferLayout.struct([ BufferLayout.u8("instruction"), Layout.uint64("liquidityAmount"), - BufferLayout.u8("maxUtilizationRate") + BufferLayout.u8("maxUtilizationRate"), ]); const data = Buffer.alloc(dataLayout.span); @@ -172,7 +178,7 @@ export const depositInstruction = ( reserveAuthority: PublicKey, reserveAccount: PublicKey, reserveSupply: PublicKey, - collateralMint: PublicKey, + collateralMint: PublicKey ): TransactionInstruction => { const dataLayout = BufferLayout.struct([ BufferLayout.u8("instruction"), @@ -212,7 +218,7 @@ export const withdrawInstruction = ( reserveAccount: PublicKey, collateralMint: PublicKey, reserveSupply: PublicKey, - authority: PublicKey, + authority: PublicKey ): TransactionInstruction => { const dataLayout = BufferLayout.struct([ BufferLayout.u8("instruction"), @@ -244,4 +250,3 @@ export const withdrawInstruction = ( data, }); }; - diff --git a/src/routes.tsx b/src/routes.tsx index d333794..1b7c3e3 100644 --- a/src/routes.tsx +++ b/src/routes.tsx @@ -7,7 +7,7 @@ import { MarketProvider } from "./contexts/market"; import { LendingProvider } from "./contexts/lending"; import { AppLayout } from "./components/Layout"; -import { +import { HomeView, DepositView, DepositReserveView, @@ -17,7 +17,7 @@ import { BorrowReserveView, WithdrawView, FaucetView, - } from './views'; +} from "./views"; export function Routes() { return ( @@ -31,13 +31,27 @@ export function Routes() { } /> - } /> + } + /> } /> - } /> - } /> + } + /> + } + /> } /> } /> - } /> + } + /> } /> diff --git a/src/utils/eventEmitter.ts b/src/utils/eventEmitter.ts index 3491788..d798ee9 100644 --- a/src/utils/eventEmitter.ts +++ b/src/utils/eventEmitter.ts @@ -44,7 +44,7 @@ export class EventEmitter { onCache(callback: (args: CacheUpdateEvent) => void) { this.emitter.on(CacheUpdateEvent.type, callback); - return () => this.emitter.removeListener(CacheUpdateEvent .type, callback); + return () => this.emitter.removeListener(CacheUpdateEvent.type, callback); } raiseAccountUpdated(id: string) { diff --git a/src/utils/layout.ts b/src/utils/layout.ts index 64d2e8d..b4ab6c0 100644 --- a/src/utils/layout.ts +++ b/src/utils/layout.ts @@ -32,15 +32,14 @@ export const uint64 = (property = "uint64"): unknown => { const _decode = layout.decode.bind(layout); const _encode = layout.encode.bind(layout); - layout.decode = (buffer: Buffer, offset: number) => { const data = _decode(buffer, offset); return new BN( [...data] .reverse() - .map(i => `00${i.toString(16)}`.slice(-2)) - .join(''), - 16, + .map((i) => `00${i.toString(16)}`.slice(-2)) + .join(""), + 16 ); }; @@ -65,15 +64,14 @@ export const uint128 = (property = "uint128"): unknown => { const _decode = layout.decode.bind(layout); const _encode = layout.encode.bind(layout); - layout.decode = (buffer: Buffer, offset: number) => { const data = _decode(buffer, offset); return new BN( [...data] .reverse() - .map(i => `00${i.toString(16)}`.slice(-2)) - .join(''), - 16, + .map((i) => `00${i.toString(16)}`.slice(-2)) + .join(""), + 16 ); }; @@ -89,7 +87,6 @@ export const uint128 = (property = "uint128"): unknown => { return _encode(b, buffer, offset); }; - return layout; }; @@ -121,4 +118,4 @@ export const rustString = (property = "string"): unknown => { }; return rsl; -}; \ No newline at end of file +}; diff --git a/src/utils/utils.ts b/src/utils/utils.ts index b9da1bb..46f34a4 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -53,7 +53,7 @@ export function getTokenName( shorten = true ): string { if (!mintAddress) { - return 'N/A'; + return "N/A"; } const knownSymbol = map.get(mintAddress)?.tokenSymbol; @@ -66,9 +66,10 @@ export function getTokenName( export function getTokenIcon( map: KnownTokenMap, - mintAddress?: string | PublicKey, + mintAddress?: string | PublicKey ): string | undefined { - const address = typeof mintAddress === 'string' ? mintAddress : mintAddress?.toBase58(); + const address = + typeof mintAddress === "string" ? mintAddress : mintAddress?.toBase58(); if (!address) { return; } @@ -101,7 +102,7 @@ export function toLamports( typeof account === "number" ? account : account.info.amount?.toNumber(); const precision = Math.pow(10, mint?.decimals || 0); - return (amount * precision); + return amount * precision; } export function fromLamports( @@ -171,12 +172,12 @@ const numberFormater = new Intl.NumberFormat("en-US", { export const formatNumber = { format: (val?: number) => { if (!val) { - return '--'; + return "--"; } return numberFormater.format(val); - } -} + }, +}; export const formatPct = new Intl.NumberFormat("en-US", { style: "percent", diff --git a/src/views/borrow/index.tsx b/src/views/borrow/index.tsx index addfb17..a4599fe 100644 --- a/src/views/borrow/index.tsx +++ b/src/views/borrow/index.tsx @@ -1,7 +1,7 @@ import React from "react"; -import { useLendingReserves } from '../../hooks'; -import { BorrowItem } from './item'; -import './itemStyle.less'; +import { useLendingReserves } from "../../hooks"; +import { BorrowItem } from "./item"; +import "./itemStyle.less"; export const BorrowView = () => { const { reserveAccounts } = useLendingReserves(); @@ -13,7 +13,9 @@ export const BorrowView = () => {
APY
Action
- {reserveAccounts.map(account => )} + {reserveAccounts.map((account) => ( + + ))}
); -} \ No newline at end of file +}; diff --git a/src/views/borrow/item.tsx b/src/views/borrow/item.tsx index 449d10d..7fd43ea 100644 --- a/src/views/borrow/item.tsx +++ b/src/views/borrow/item.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useCollateralBalance, useTokenName } from '../../hooks'; +import { useCollateralBalance, useTokenName } from "../../hooks"; import { LendingReserve } from "../../models/lending"; import { TokenIcon } from "../../components/TokenIcon"; import { formatNumber } from "../../utils/utils"; @@ -7,24 +7,34 @@ import { Button, Card } from "antd"; import { Link } from "react-router-dom"; import { PublicKey } from "@solana/web3.js"; -export const BorrowItem = (props: { reserve: LendingReserve, address: PublicKey }) => { +export const BorrowItem = (props: { + reserve: LendingReserve; + address: PublicKey; +}) => { const name = useTokenName(props.reserve.liquidityMint); // TODO: calculate avilable amount... based on total owned collateral across all the reserves const { balance: collateralBalance } = useCollateralBalance(props.reserve); - return - -
- {name} -
{formatNumber.format(collateralBalance)} {name}
-
--
-
- + return ( + + +
+ + + {name} + +
+ {formatNumber.format(collateralBalance)} {name} +
+
--
+
+ +
-
- - ; -} \ No newline at end of file + + + ); +}; diff --git a/src/views/borrowReserve/index.tsx b/src/views/borrowReserve/index.tsx index f5c7b8c..a7bcbb9 100644 --- a/src/views/borrowReserve/index.tsx +++ b/src/views/borrowReserve/index.tsx @@ -1,10 +1,13 @@ -import React, { } from "react"; -import { useLendingReserve } from '../../hooks'; +import React from "react"; +import { useLendingReserve } from "../../hooks"; import { useParams } from "react-router-dom"; -import './style.less'; +import "./style.less"; -import { BorrowInput } from '../../components/BorrowInput'; -import { SideReserveOverview, SideReserveOverviewMode } from '../../components/SideReserveOverview'; +import { BorrowInput } from "../../components/BorrowInput"; +import { + SideReserveOverview, + SideReserveOverviewMode, +} from "../../components/SideReserveOverview"; export const BorrowReserveView = () => { const { id } = useParams<{ id: string }>(); @@ -15,17 +18,21 @@ export const BorrowReserveView = () => { return null; } - return
-
- - + return ( +
+
+ + +
-
; -} \ No newline at end of file + ); +}; diff --git a/src/views/dashboard/index.tsx b/src/views/dashboard/index.tsx index f176526..3065fbf 100644 --- a/src/views/dashboard/index.tsx +++ b/src/views/dashboard/index.tsx @@ -1,11 +1,9 @@ import React from "react"; export const DashboardView = () => { - - return
- DASHBOARD: - TODO: - 1. Add deposits - 2. Add obligations -
; -} \ No newline at end of file + return ( +
+ DASHBOARD: TODO: 1. Add deposits 2. Add obligations +
+ ); +}; diff --git a/src/views/deposit/index.tsx b/src/views/deposit/index.tsx index 68fddf6..6f08b55 100644 --- a/src/views/deposit/index.tsx +++ b/src/views/deposit/index.tsx @@ -1 +1 @@ -export * from './view'; \ No newline at end of file +export * from "./view"; diff --git a/src/views/deposit/view/index.tsx b/src/views/deposit/view/index.tsx index 31f2d50..2201b4e 100644 --- a/src/views/deposit/view/index.tsx +++ b/src/views/deposit/view/index.tsx @@ -1,7 +1,7 @@ import React from "react"; -import { useLendingReserves } from '../../../hooks'; -import { ReserveItem } from './item'; -import './itemStyle.less'; +import { useLendingReserves } from "../../../hooks"; +import { ReserveItem } from "./item"; +import "./itemStyle.less"; export const DepositView = () => { const { reserveAccounts } = useLendingReserves(); @@ -14,7 +14,9 @@ export const DepositView = () => {
APY
Action
- {reserveAccounts.map(account => )} + {reserveAccounts.map((account) => ( + + ))}
); -}; \ No newline at end of file +}; diff --git a/src/views/deposit/view/item.tsx b/src/views/deposit/view/item.tsx index 39805e0..b1bc3d2 100644 --- a/src/views/deposit/view/item.tsx +++ b/src/views/deposit/view/item.tsx @@ -1,5 +1,9 @@ import React from "react"; -import { useCollateralBalance, useTokenName, useUserBalance } from '../../../hooks'; +import { + useCollateralBalance, + useTokenName, + useUserBalance, +} from "../../../hooks"; import { LendingReserve } from "../../../models/lending"; import { TokenIcon } from "../../../components/TokenIcon"; import { formatNumber } from "../../../utils/utils"; @@ -7,24 +11,36 @@ 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 }) => { +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 - -
- {name} -
{formatNumber.format(tokenBalance)} {name}
-
{formatNumber.format(collateralBalance)} {name}
-
--
-
- + return ( + + +
+ + + {name} + +
+ {formatNumber.format(tokenBalance)} {name} +
+
+ {formatNumber.format(collateralBalance)} {name} +
+
--
+
+ +
-
- - ; -} \ No newline at end of file + + + ); +}; diff --git a/src/views/depositReserve/index.tsx b/src/views/depositReserve/index.tsx index 385af54..846ce4d 100644 --- a/src/views/depositReserve/index.tsx +++ b/src/views/depositReserve/index.tsx @@ -1,11 +1,14 @@ -import React, { } from "react"; -import { useLendingReserve } from '../../hooks'; +import React from "react"; +import { useLendingReserve } from "../../hooks"; import { useParams } from "react-router-dom"; -import './style.less'; +import "./style.less"; -import { DepositInput } from '../../components/DepositInput'; -import { DepositInfoLine } from '../../components/DepositInfoLine'; -import { SideReserveOverview, SideReserveOverviewMode } from '../../components/SideReserveOverview'; +import { DepositInput } from "../../components/DepositInput"; +import { DepositInfoLine } from "../../components/DepositInfoLine"; +import { + SideReserveOverview, + SideReserveOverviewMode, +} from "../../components/SideReserveOverview"; export const DepositReserveView = () => { const { id } = useParams<{ id: string }>(); @@ -16,21 +19,26 @@ export const DepositReserveView = () => { return null; } - return
- + -
- - + /> +
+ + +
-
; -} \ No newline at end of file + ); +}; diff --git a/src/views/faucet/index.tsx b/src/views/faucet/index.tsx index c900013..d8878d3 100644 --- a/src/views/faucet/index.tsx +++ b/src/views/faucet/index.tsx @@ -7,30 +7,39 @@ import { LAMPORTS_PER_SOL } from "@solana/web3.js"; export const FaucetView = () => { const connection = useConnection(); const { wallet } = useWallet(); - + const airdrop = useCallback(() => { connection.requestAirdrop(wallet.publicKey, 1 * LAMPORTS_PER_SOL); - }, [wallet, connection]) + }, [wallet, connection]); const bodyStyle: React.CSSProperties = { - display: 'flex', + display: "flex", flex: 1, - justifyContent: 'center', - alignItems: 'center', - height: '100%', + justifyContent: "center", + alignItems: "center", + height: "100%", }; - return (
- -
+ +
- This Faucet will help you fund your accounts outside of Solana main network. + This Faucet will help you fund your accounts outside of Solana main + network.
- +
); -} \ No newline at end of file +}; diff --git a/src/views/home/index.tsx b/src/views/home/index.tsx index 415035d..9fd4712 100644 --- a/src/views/home/index.tsx +++ b/src/views/home/index.tsx @@ -1,21 +1,25 @@ import React from "react"; -import { useLendingReserves } from '../../hooks'; +import { useLendingReserves } from "../../hooks"; import { LendingReserveItem } from "./item"; -import './itemStyle.less'; +import "./itemStyle.less"; export const HomeView = () => { const { reserveAccounts } = useLendingReserves(); // TODO: add total Liquidity amount ... - return
-
-
Asset
-
Market Size
-
Total Borrowed
-
Deposit APY
-
Borrow APY
+ return ( +
+
+
Asset
+
Market Size
+
Total Borrowed
+
Deposit APY
+
Borrow APY
+
+ {reserveAccounts.map((account) => ( + + ))}
- {reserveAccounts.map(account => )} -
; -} \ No newline at end of file + ); +}; diff --git a/src/views/home/item.tsx b/src/views/home/item.tsx index f8d3954..1f319e7 100644 --- a/src/views/home/item.tsx +++ b/src/views/home/item.tsx @@ -1,5 +1,5 @@ import React from "react"; -import { useTokenName } from '../../hooks'; +import { useTokenName } from "../../hooks"; import { LendingReserve } from "../../models/lending"; import { TokenIcon } from "../../components/TokenIcon"; import { formatNumber, fromLamports } from "../../utils/utils"; @@ -8,26 +8,40 @@ import { Link } from "react-router-dom"; import { PublicKey } from "@solana/web3.js"; import { useMint } from "../../contexts/accounts"; -export const LendingReserveItem = (props: { reserve: LendingReserve, address: PublicKey }) => { +export const LendingReserveItem = (props: { + reserve: LendingReserve; + address: PublicKey; +}) => { const name = useTokenName(props.reserve.liquidityMint); const liquidityMint = useMint(props.reserve.liquidityMint); - const totalLiquidity = fromLamports(props.reserve.totalLiquidity.toNumber(), liquidityMint); + const totalLiquidity = fromLamports( + props.reserve.totalLiquidity.toNumber(), + liquidityMint + ); const totalBorrows = props.reserve.totalBorrows.toString(); console.log(liquidityMint); - return - -
- {name} -
{formatNumber.format(totalLiquidity)} {name}
-
{totalBorrows} {name}
-
--
-
--
-
- -
- ; -} \ No newline at end of file + return ( + + +
+ + + {name} + +
+ {formatNumber.format(totalLiquidity)} {name} +
+
+ {totalBorrows} {name} +
+
--
+
--
+
+
+ + ); +}; diff --git a/src/views/index.tsx b/src/views/index.tsx index fd71cd5..b68beef 100644 --- a/src/views/index.tsx +++ b/src/views/index.tsx @@ -1,9 +1,9 @@ -export { HomeView } from './home'; -export { BorrowView } from './borrow'; -export { BorrowReserveView } from './borrowReserve'; -export { DashboardView } from './dashboard'; -export { DepositView } from './deposit'; -export { DepositReserveView } from './depositReserve'; -export { ReserveView } from './reserve'; -export { WithdrawView } from './withdraw'; -export { FaucetView } from './faucet'; +export { HomeView } from "./home"; +export { BorrowView } from "./borrow"; +export { BorrowReserveView } from "./borrowReserve"; +export { DashboardView } from "./dashboard"; +export { DepositView } from "./deposit"; +export { DepositReserveView } from "./depositReserve"; +export { ReserveView } from "./reserve"; +export { WithdrawView } from "./withdraw"; +export { FaucetView } from "./faucet"; diff --git a/src/views/reserve/index.tsx b/src/views/reserve/index.tsx index d866494..78806fe 100644 --- a/src/views/reserve/index.tsx +++ b/src/views/reserve/index.tsx @@ -1,10 +1,10 @@ -import React, { } from "react"; -import { useLendingReserve } from './../../hooks'; +import React from "react"; +import { useLendingReserve } from "./../../hooks"; import { useParams } from "react-router-dom"; -import './style.less'; +import "./style.less"; -import { UserLendingCard } from './../../components/UserLendingCard'; -import { ReserveStatus } from './../../components/ReserveStatus'; +import { UserLendingCard } from "./../../components/UserLendingCard"; +import { ReserveStatus } from "./../../components/ReserveStatus"; export const ReserveView = () => { const { id } = useParams<{ id: string }>(); @@ -15,16 +15,20 @@ export const ReserveView = () => { return null; } - return
-
- - + return ( +
+
+ + +
-
; -} \ No newline at end of file + ); +}; diff --git a/src/views/withdraw/index.tsx b/src/views/withdraw/index.tsx index 4a02ade..969aa19 100644 --- a/src/views/withdraw/index.tsx +++ b/src/views/withdraw/index.tsx @@ -1,11 +1,14 @@ -import React, { } from "react"; -import { useLendingReserve } from '../../hooks'; +import React from "react"; +import { useLendingReserve } from "../../hooks"; import { useParams } from "react-router-dom"; -import './style.less'; +import "./style.less"; -import { WithdrawInput } from '../../components/WithdrawInput'; -import { DepositInfoLine } from '../../components/DepositInfoLine'; -import { SideReserveOverview, SideReserveOverviewMode } from '../../components/SideReserveOverview'; +import { WithdrawInput } from "../../components/WithdrawInput"; +import { DepositInfoLine } from "../../components/DepositInfoLine"; +import { + SideReserveOverview, + SideReserveOverviewMode, +} from "../../components/SideReserveOverview"; export const WithdrawView = () => { const { id } = useParams<{ id: string }>(); @@ -16,21 +19,26 @@ export const WithdrawView = () => { return null; } - return
- + -
- - + /> +
+ + +
-
; -} \ No newline at end of file + ); +};