diff --git a/app/lending/components/cTokenRow.tsx b/app/lending/components/cTokenRow.tsx new file mode 100644 index 00000000..6e02e6b4 --- /dev/null +++ b/app/lending/components/cTokenRow.tsx @@ -0,0 +1,64 @@ +import Button from "@/components/button/button"; +import Container from "@/components/container/container"; +import Icon from "@/components/icon/icon"; +import Spacer from "@/components/layout/spacer"; +import Text from "@/components/text"; +import { CTokenWithUserData } from "@/hooks/lending/interfaces/tokens"; +import { formatBalance } from "@/utils/tokenBalances.utils"; + +export const CTokenRow = ({ + cToken, + onClick, +}: { + cToken: CTokenWithUserData; + onClick: () => void; +}) => [ + <> + + + + {cToken.underlying.name} + + , + + {cToken.supplyApy + "%"} + , + + {formatBalance( + cToken.userDetails?.balanceOfUnderlying ?? "0", + cToken.underlying.decimals, + { + commify: true, + } + )} + , + + {formatBalance( + cToken.userDetails?.supplyBalanceInUnderlying ?? "0", + cToken.underlying.decimals, + { + commify: true, + } + )} + , + + {formatBalance(cToken.collateralFactor, 16) + "%"} + , + + + + + , +]; diff --git a/app/lending/components/highlightCard.module.scss b/app/lending/components/highlightCard.module.scss new file mode 100644 index 00000000..d601f67a --- /dev/null +++ b/app/lending/components/highlightCard.module.scss @@ -0,0 +1,39 @@ +.container { + background: var(--card-sub-surface-color, #dfdfdf); + box-shadow: 6px 6px 0px 0px rgba(17, 17, 17, 0.15); + + margin: 0 auto; + // width: 920px; + // height: 320px; + width: 100%; + padding-bottom: 1rem; + position: relative; + overflow: hidden; +} + +.header { + background: var(--card-primary-color); + padding: 1rem 2rem; + display: flex; + justify-content: space-between; +} + +.amounts { + padding: 1rem 2rem; + display: flex; + justify-content: space-between; +} + +.actions { + padding: 1rem 2rem; + display: flex; + width: 70%; + gap: 2rem; +} + +.logo { + position: absolute; + bottom: 0; + right: 0; + transform: translate(16%, 16%); +} diff --git a/app/lending/components/highlightCard.tsx b/app/lending/components/highlightCard.tsx new file mode 100644 index 00000000..fc112c24 --- /dev/null +++ b/app/lending/components/highlightCard.tsx @@ -0,0 +1,100 @@ +import styles from "./highlightCard.module.scss"; +import Button from "@/components/button/button"; +import Image from "next/image"; +import Item from "./item"; +import Icon from "@/components/icon/icon"; +interface Props { + token: { + name: string; + imgUrl: string; + supplyAPR: string; + borrowAPR: string; + walletBalance?: string; + amountStaked?: string; + outStandingDebt?: string; + supply: () => void; + borrow: () => void; + }; +} +const HighlightCard = (props: Props) => { + return ( +
+ {"logo"} +
+ + + +
+
+ + } + /> + + } + /> + +
+ +
+ + + +
+
+ ); +}; + +export default HighlightCard; diff --git a/app/lending/components/item.module.scss b/app/lending/components/item.module.scss new file mode 100644 index 00000000..ef86b2d7 --- /dev/null +++ b/app/lending/components/item.module.scss @@ -0,0 +1,18 @@ +.item { + display: flex; + flex-grow: 1; + width: 100%; + flex-direction: column; +} + +.title { + font-size: 16px; +} + +.value { + font-size: 32px !important; +} + +.postChild { + margin-left: -1rem; +} diff --git a/app/lending/components/item.tsx b/app/lending/components/item.tsx new file mode 100644 index 00000000..eaa67c05 --- /dev/null +++ b/app/lending/components/item.tsx @@ -0,0 +1,28 @@ +import styles from "./item.module.scss"; +import Text from "@/components/text"; + +type ItemProps = { + name: string; + value: string; + postChild?: React.ReactNode; + theme?: + | "primary-light" + | "primary-dark" + | "secondary-light" + | "secondary-dark" + | undefined; +}; + +const Item = ({ name, value, theme, postChild }: ItemProps) => ( +
+ + {name} + + + {value}{" "} + {postChild && {postChild}} + +
+); + +export default Item; diff --git a/app/lending/components/modal/modal.module.scss b/app/lending/components/modal/modal.module.scss new file mode 100644 index 00000000..5bd218ec --- /dev/null +++ b/app/lending/components/modal/modal.module.scss @@ -0,0 +1,26 @@ +.container { + display: flex; + flex-direction: column; + // min-height: 42rem; + margin: 0 -15px; + margin-bottom: -15px; +} + +.card { + border-radius: var(--border-radius, 0px); + background: var(--card-surface-color, #f1f1f1); + padding: 1rem; + gap: 10px; + /* old */ + box-shadow: -3px -3px 0px 0px rgba(17, 17, 17, 0.2) inset, + 2px 2px 0px 0px rgba(255, 255, 255, 0.4) inset; +} + +.content { + display: flex; + flex-direction: column; + justify-content: stretch; + align-items: center; + width: 100%; + padding: 1rem; +} diff --git a/app/lending/components/modal/modal.tsx b/app/lending/components/modal/modal.tsx new file mode 100644 index 00000000..a9356b44 --- /dev/null +++ b/app/lending/components/modal/modal.tsx @@ -0,0 +1,292 @@ +import Button from "@/components/button/button"; +import Text from "@/components/text"; +import Input from "@/components/input/input"; +import { CTokenLendingTxTypes } from "@/hooks/lending/interfaces/lendingTxTypes"; +import { CTokenWithUserData } from "@/hooks/lending/interfaces/tokens"; +import { maxAmountForLendingTx } from "@/utils/clm/limits.utils"; +import { UserLMPosition } from "@/hooks/lending/interfaces/userPositions"; +import styles from "./modal.module.scss"; +import Tabs from "@/components/tabs/tabs"; +import Image from "next/image"; +import Container from "@/components/container/container"; +import { formatBalance } from "@/utils/tokenBalances.utils"; +import Icon from "@/components/icon/icon"; +import Spacer from "@/components/layout/spacer"; +interface Props { + selectedToken: CTokenWithUserData | null; + transaction: { + performTx: (amount: string, txType: CTokenLendingTxTypes) => void; + canPerformTx: (amount: string, txType: CTokenLendingTxTypes) => boolean; + }; + currentAction: CTokenLendingTxTypes; + setCurrentAction: (action: CTokenLendingTxTypes) => void; + amount: string; + setAmount: (amount: string) => void; + clmPosition: { + position: UserLMPosition; + general: { + maxAccountLiquidity: string; + outstandingDebt: string; + percentLimitUsed: string; + netApr: string; + }; + }; +} + +interface LSProps { + action: CTokenLendingTxTypes; +} +export const LendingModal = ({ + selectedToken, + transaction, + currentAction, + setCurrentAction, + amount, + setAmount, + clmPosition, +}: Props) => { + const LendingActionSwitch = ({ action }: LSProps) => ( + + ); + + function data() { + if (selectedToken == null) { + return No Active Token; + } + + return ( + <> + + {selectedToken.symbol} + + name: {selectedToken.name} + Address: {selectedToken.address} + BorrowApy: {selectedToken.borrowApy} + BorrowCap: {selectedToken.borrowCap} + Cash: {selectedToken.cash} + + CollateralFactor: {selectedToken.collateralFactor} + + Decimals: {selectedToken.decimals} + DistApy: {selectedToken.distApy} + Exchange Rate: {selectedToken.exchangeRate} + IsListed: {selectedToken.isListed ? "yes" : "no"} + Liquidity: {selectedToken.liquidity} + Underlying Price: {selectedToken.price} + Supply Apy: {selectedToken.supplyApy} +

----

+ + Underlying: + + Address: {selectedToken.underlying.address} + Decimals: {selectedToken.underlying.decimals} + Symbol: {selectedToken.underlying.symbol} + Name: {selectedToken.underlying.name} +

----

+ + User Data: + + + CToken Balance: {selectedToken.userDetails?.balanceOfCToken} + + + Underlying Balance: {selectedToken.userDetails?.balanceOfUnderlying} + + + Borrow Balance: {selectedToken.userDetails?.borrowBalance} + + Rewards: {selectedToken.userDetails?.rewards} + + Is Collateral:{" "} + {selectedToken.userDetails?.isCollateral ? "yes" : "no"} + + + Supply Balance In Underlying:{" "} + {selectedToken.userDetails?.supplyBalanceInUnderlying} + + + Allowance Underlying: {selectedToken.userDetails?.underlyingAllowance} + + { + setAmount(val.target.value); + }} + /> +
+ + + + +
+ + + ); + } + + function Content(token: CTokenWithUserData) { + return ( +
+ + {"Transaction"} + + + + {token.symbol} + + + + + + + + + + + + + + + + + + +
+ { + setAmount(val.target.value); + }} + placeholder="0.0" + value={amount} + /> + + +
+
+ ); + } + return ( +
+ {selectedToken ? ( + <> + + + ) : ( + No Active Token + )} +
+ ); +}; + +const Card = ({ + name, + value, + note, +}: { + name: string; + value: string; + note?: boolean; +}) => ( + + + {name} + + + {value}{" "} + + {note && ( + + )} + + + +); diff --git a/app/lending/components/outlineCard.module.scss b/app/lending/components/outlineCard.module.scss new file mode 100644 index 00000000..30554270 --- /dev/null +++ b/app/lending/components/outlineCard.module.scss @@ -0,0 +1,32 @@ +.container { + width: 100%; + aspect-ratio: 1; + border-top: 1px solid var(--card-primary-color); + border-bottom: 1px solid var(--card-primary-color); + position: relative; + display: flex; + padding: 1rem; + flex-direction: column; + gap: 10px; + &::before { + content: ""; + position: absolute; + top: -1px; + left: 0; + width: calc(100% - 1px); + height: 10px; + border-left: 1px solid var(--card-primary-color); + border-right: 1px solid var(--card-primary-color); + } + + &::after { + content: ""; + position: absolute; + bottom: 0; + left: 0; + width: calc(100% - 1px); + height: 10px; + border-left: 1px solid var(--card-primary-color); + border-right: 1px solid var(--card-primary-color); + } +} diff --git a/app/lending/components/outlineCard.tsx b/app/lending/components/outlineCard.tsx new file mode 100644 index 00000000..2948d1cb --- /dev/null +++ b/app/lending/components/outlineCard.tsx @@ -0,0 +1,9 @@ +import styles from "./outlineCard.module.scss"; +interface Props { + children: React.ReactNode; +} +const OutlineCard = (props: Props) => { + return
{props.children}
; +}; + +export default OutlineCard; diff --git a/app/lending/lending.module.scss b/app/lending/lending.module.scss new file mode 100644 index 00000000..b052b7ef --- /dev/null +++ b/app/lending/lending.module.scss @@ -0,0 +1,42 @@ +.container { + display: flex; + flex-direction: column; + align-items: center; +} + +.title { + font-size: 42px !important; + padding-left: 4rem; + text-align: left; + width: 100%; + max-width: 1500px; +} + +.grid { + display: flex; + gap: 2rem; + padding: 2rem; + padding-top: 0rem; + max-width: 1500px; +} + +.highlightCard { + max-width: 1000px; + width: 100%; + display: flex; + justify-content: stretch; +} + +.mainTable { + max-width: 1000px; + width: 100%; + display: flex; + justify-content: stretch; +} + +.widget1 { + // width: 70%; +} + +.widget2 { +} diff --git a/app/lending/page.tsx b/app/lending/page.tsx index 973c9926..faf94596 100644 --- a/app/lending/page.tsx +++ b/app/lending/page.tsx @@ -1,18 +1,23 @@ "use client"; import Button from "@/components/button/button"; +import styles from "./lending.module.scss"; import Icon from "@/components/icon/icon"; import Input from "@/components/input/input"; import Spacer from "@/components/layout/spacer"; import Modal from "@/components/modal/modal"; import Table from "@/components/table/table"; -import { CTokenLendingTxTypes } from "@/hooks/lending/interfaces/lendingTxTypes"; -import { CTokenWithUserData } from "@/hooks/lending/interfaces/tokens"; -import { maxAmountForLendingTx } from "@/utils/clm/limits.utils"; + import { formatBalance } from "@/utils/tokenBalances.utils"; import { useLendingCombo } from "./utils"; import Text from "@/components/text"; import Container from "@/components/container/container"; +import HighlightCard from "./components/highlightCard"; +import OutlineCard from "./components/outlineCard"; +import Item from "./components/item"; +import LoadingIcon from "@/components/loader/loading"; +import { LendingModal } from "./components/modal/modal"; +import { CTokenRow } from "./components/cTokenRow"; interface LendingProps { Asset: string; @@ -28,7 +33,8 @@ interface LendingProps { } export default function LendingPage() { - const { cTokens, clmPosition, transaction, selection } = useLendingCombo(); + const { cTokens, clmPosition, transaction, selection, isLoading } = + useLendingCombo(); const { cNote, rwas } = cTokens; const { currentAction, @@ -40,229 +46,206 @@ export default function LendingPage() { amount, setAmount, } = selection; - interface LSProps { - action: CTokenLendingTxTypes; - } - const LendingActionSwitch = ({ action }: LSProps) => ( - - ); - - const CTokenRow = ({ cToken }: { cToken: CTokenWithUserData }) => [ - <> - - - - {cToken.underlying.name} - - , - - {cToken.supplyApy + "%"} - , - - {formatBalance( - cToken.userDetails?.balanceOfUnderlying ?? "0", - cToken.underlying.decimals, - { - commify: true, - } - )} - , - - {formatBalance( - cToken.userDetails?.supplyBalanceInUnderlying ?? "0", - cToken.underlying.decimals, - { - commify: true, - } - )} - , - - {formatBalance(cToken.collateralFactor, 16) + "%"} - , - - - , - - , - ]; return ( -
- +
+ Lending - setModalOpen(false)}> - <> - {selectedToken && ( - <> - - {selectedToken.symbol} - - name: {selectedToken.name} - Address: {selectedToken.address} - BorrowApy: {selectedToken.borrowApy} - BorrowCap: {selectedToken.borrowCap} - Cash: {selectedToken.cash} - - CollateralFactor: {selectedToken.collateralFactor} - - Decimals: {selectedToken.decimals} - DistApy: {selectedToken.distApy} - Exchange Rate: {selectedToken.exchangeRate} - - IsListed: {selectedToken.isListed ? "yes" : "no"} - - Liquidity: {selectedToken.liquidity} - Underlying Price: {selectedToken.price} - Supply Apy: {selectedToken.supplyApy} -

----

- - Underlying: - - Address: {selectedToken.underlying.address} - - Decimals: {selectedToken.underlying.decimals} - - Symbol: {selectedToken.underlying.symbol} - Name: {selectedToken.underlying.name} -

----

- - User Data: - - - CToken Balance: {selectedToken.userDetails?.balanceOfCToken} - - - Underlying Balance:{" "} - {selectedToken.userDetails?.balanceOfUnderlying} - - - Borrow Balance: {selectedToken.userDetails?.borrowBalance} - - - Rewards: {selectedToken.userDetails?.rewards} - - - Is Collateral:{" "} - {selectedToken.userDetails?.isCollateral ? "yes" : "no"} - - - Supply Balance In Underlying:{" "} - {selectedToken.userDetails?.supplyBalanceInUnderlying} - - - Allowance Underlying:{" "} - {selectedToken.userDetails?.underlyingAllowance} - - { - setAmount(val.target.value); + setModalOpen(false)} + title="Lending" + width="32rem" + > + + + + + +
+ {isLoading ? ( + + + + ) : cNote ? ( + { + setSelectedToken(cNote); + setModalOpen(true); + }, + + borrow: () => { + setSelectedToken(cNote); + setModalOpen(true); + }, }} /> -
- - - - -
-
+
+ {isLoading ? ( + - CONFIRM - - - )} - - -
- {" "} - - USER POSITION - - - Maximum Account Liquidity: {} - {formatBalance(clmPosition.general.maxAccountLiquidity, 18, { - commify: true, - precision: 2, - })} - - - Outstanding Debt:{" "} - {formatBalance(clmPosition.general.outstandingDebt, 18, { - commify: true, - precision: 2, - })} - - - Percent Limit Used: {clmPosition.general.percentLimitUsed + "%"} - - - Average Apr: {clmPosition.general.netApr + "%"} - {" "} -
- {cNote && ( - - )} - {rwas.length > 0 && ( -
CTokenRow({ cToken }))]} - /> - )} + + + ) : rwas.length > 0 ? ( +
+ CTokenRow({ + cToken, + onClick: () => { + setSelectedToken(cToken); + setModalOpen(true); + }, + }) + ), + ]} + /> + ) : ( + No RWAS tokens available + )} + + + + +
+ + + } + /> + + } + /> + + } + /> + +
+ +
+ + + + + + +
+
+ ); } diff --git a/app/lending/utils.tsx b/app/lending/utils.tsx index b84d7d68..917b40a3 100644 --- a/app/lending/utils.tsx +++ b/app/lending/utils.tsx @@ -19,6 +19,7 @@ interface LendingComboReturn { cNote: CTokenWithUserData | undefined; rwas: CTokenWithUserData[]; }; + isLoading: boolean; clmPosition: { position: UserLMPosition; general: { @@ -47,7 +48,7 @@ export function useLendingCombo(): LendingComboReturn { // params for useLending hook const { data: signer } = useWalletClient(); const chainId = signer?.chain.id === 7701 ? 7701 : 7700; - const { cTokens, position, loading, transaction } = useLending({ + const { cTokens, position, isLoading, transaction } = useLending({ chainId, lmType: "lending", userEthAddress: signer?.account.address, @@ -125,6 +126,7 @@ export function useLendingCombo(): LendingComboReturn { cNote, rwas, }, + isLoading, clmPosition: { position, general: { diff --git a/components/loader/loading.tsx b/components/loader/loading.tsx index ddcb3b89..63dd5468 100644 --- a/components/loader/loading.tsx +++ b/components/loader/loading.tsx @@ -9,6 +9,7 @@ interface Props { const LoadingIcon = ({ size, className }: Props) => { return ( { {title && (
-

{title}

+ + {title} +
)}
{children}
diff --git a/components/transactions/TxItem.tsx b/components/transactions/TxItem.tsx index 1d4cb0cc..a5c369f3 100644 --- a/components/transactions/TxItem.tsx +++ b/components/transactions/TxItem.tsx @@ -121,7 +121,7 @@ const TxItem = (props: TxItemProps) => { )} {props.tx.tx.bridge && props.tx.tx.bridge.lastStatus !== "NONE" && ( - <> + Bridge Status - {props.tx.tx.bridge.lastStatus.toLowerCase()} @@ -131,7 +131,7 @@ const TxItem = (props: TxItemProps) => { {formatSecondsToMinutes(props.tx.tx.bridge.timeLeft)} )} - + )} diff --git a/components/transactions/transactions.module.scss b/components/transactions/transactions.module.scss index 25940c75..6c114ad1 100644 --- a/components/transactions/transactions.module.scss +++ b/components/transactions/transactions.module.scss @@ -21,7 +21,6 @@ align-items: center; width: 100%; cursor: pointer; - user-select: none; &:hover { @@ -31,7 +30,7 @@ .collapsable { overflow-x: hidden; - overflow-y: scroll; + overflow-y: hidden; max-height: 0; transition: max-height 0.5s linear; position: relative; diff --git a/hooks/lending/interfaces/hookParams.ts b/hooks/lending/interfaces/hookParams.ts index 8205fc3d..e382c41b 100644 --- a/hooks/lending/interfaces/hookParams.ts +++ b/hooks/lending/interfaces/hookParams.ts @@ -13,7 +13,7 @@ export interface LendingHookInputParams { export interface LendingHookReturn { cTokens: CTokenWithUserData[]; position: UserLMPosition; - loading: boolean; + isLoading: boolean; transaction: { canPerformLendingTx: ( txParams: CTokenLendingTransactionParams diff --git a/hooks/lending/useLending.ts b/hooks/lending/useLending.ts index 861b0c2a..c7b9ea9d 100644 --- a/hooks/lending/useLending.ts +++ b/hooks/lending/useLending.ts @@ -101,7 +101,7 @@ export default function useLending( return { cTokens, position, - loading: loadingCTokens, + isLoading: loadingCTokens, transaction: { canPerformLendingTx, createNewLendingFlow: createNewCTokenLendingFlow, diff --git a/provider/rainbowProvider.tsx b/provider/rainbowProvider.tsx index 1efb18ef..83c4eca6 100644 --- a/provider/rainbowProvider.tsx +++ b/provider/rainbowProvider.tsx @@ -1,5 +1,14 @@ import "@rainbow-me/rainbowkit/styles.css"; -import { getDefaultWallets, RainbowKitProvider } from "@rainbow-me/rainbowkit"; +import { + connectorsForWallets, + getDefaultWallets, + RainbowKitProvider, +} from "@rainbow-me/rainbowkit"; +import { + injectedWallet, + rainbowWallet, + walletConnectWallet, +} from "@rainbow-me/rainbowkit/wallets"; import { Chain, configureChains, createConfig, WagmiConfig } from "wagmi"; import { publicProvider } from "wagmi/providers/public"; import * as EVM_CHAINS from "@/config/networks/evm"; @@ -51,9 +60,22 @@ const { connectors } = getDefaultWallets({ projectId: process.env.NEXT_PUBLIC_WALLET_CONNECT_PROJECT_ID as string, chains, }); + +const specificConnectors = connectorsForWallets([ + { + groupName: "Recommended", + wallets: [ + injectedWallet({ + chains, + }), + ], + }, +]); + const wagmiConfig = createConfig({ autoConnect: true, - connectors, + // connectors, + connectors: specificConnectors, publicClient, });