diff --git a/src/pages/_borrow/BorrowMobileCard.tsx b/src/pages/_borrow/BorrowMobileCard.tsx new file mode 100644 index 00000000..215eaea0 --- /dev/null +++ b/src/pages/_borrow/BorrowMobileCard.tsx @@ -0,0 +1,85 @@ +import { useMemo } from 'react'; + +import { Button } from '@components/Button'; +import { Loading } from '@components/Loading'; +import { usePools } from '@contexts/pool-context'; +import { useWallet } from '@contexts/wallet-context'; +import { isBalanceZero } from '@lib/converters'; +import { formatAPR, formatAmount, toDollarsFormatted } from '@lib/formatting'; +import { isNil } from 'ramda'; +import type { CurrencyBinding } from 'src/currency-bindings'; + +export interface BorrowMobileCardProps { + currency: CurrencyBinding; + onBorrowClicked: VoidFunction; +} + +export const BorrowMobileCard = ({ currency, onBorrowClicked }: BorrowMobileCardProps) => { + const { icon, name, ticker, issuerName } = currency; + + const { wallet, walletBalances } = useWallet(); + const { prices, pools } = usePools(); + const pool = pools?.[ticker]; + const price = prices?.[ticker]; + + // Does the user have some other token in their wallet to use as a collateral? + const isCollateral = !walletBalances + ? false + : Object.entries(walletBalances) + .filter(([t, _b]) => t !== ticker) + .some(([_t, b]) => b.trustLine && !isBalanceZero(b.balanceLine.balance)); + + const borrowDisabled = !wallet || !isCollateral || !pool || pool.availableBalanceTokens === 0n; + + const tooltip = useMemo(() => { + if (!pool) return 'The pool is loading'; + if (pool.availableBalanceTokens === 0n) return 'the pool has no assets to borrow'; + if (!wallet) return 'Connect a wallet first'; + if (!isCollateral) return 'Another token needed for the collateral'; + return 'Something odd happened.'; + }, [pool, wallet, isCollateral]); + + return ( +
+
+ +
+

{name}

+

+ {ticker} • {issuerName} +

+
+
+ +
+
+

Available

+

+ {pool ? formatAmount(pool.availableBalanceTokens) : } +

+

+ {!isNil(price) && !isNil(pool) && toDollarsFormatted(price, pool.availableBalanceTokens)} +

+
+
+

Borrow APY

+

{pool ? formatAPR(pool.annualInterestRate) : }

+
+
+ +
+ {borrowDisabled ? ( +
+ +
+ ) : ( + + )} +
+
+ ); +}; diff --git a/src/pages/_borrow/BorrowPage.tsx b/src/pages/_borrow/BorrowPage.tsx index 964a4f2f..8d01c31f 100644 --- a/src/pages/_borrow/BorrowPage.tsx +++ b/src/pages/_borrow/BorrowPage.tsx @@ -8,6 +8,7 @@ import { usePools } from '@contexts/pool-context'; import { useWallet } from '@contexts/wallet-context'; import { contractId } from '@contracts/loan_manager'; import { CURRENCY_BINDINGS_ARR, type CurrencyBinding } from 'src/currency-bindings'; +import { BorrowMobileCard } from './BorrowMobileCard'; import { BorrowModal } from './BorrowModal/BorrowModal'; import { BorrowableAsset } from './BorrowableAsset'; @@ -44,15 +45,26 @@ const BorrowPage = () => {

Borrow Assets

- +
{CURRENCY_BINDINGS_ARR.map((currency) => ( - openBorrowModal(currency)} /> ))} -
+
+
+ + {CURRENCY_BINDINGS_ARR.map((currency) => ( + openBorrowModal(currency)} + /> + ))} +
+
diff --git a/src/pages/_lend/LendMobileCard.tsx b/src/pages/_lend/LendMobileCard.tsx new file mode 100644 index 00000000..73e7b7f4 --- /dev/null +++ b/src/pages/_lend/LendMobileCard.tsx @@ -0,0 +1,69 @@ +import { Button } from '@components/Button'; +import { Loading } from '@components/Loading'; +import { usePools } from '@contexts/pool-context'; +import { type Balance, useWallet } from '@contexts/wallet-context'; +import { isBalanceZero } from '@lib/converters'; +import { formatAPY, formatAmount, toDollarsFormatted } from '@lib/formatting'; +import { isNil } from 'ramda'; +import type { CurrencyBinding } from 'src/currency-bindings'; + +export interface LendMobileCardProps { + currency: CurrencyBinding; + onDepositClicked: VoidFunction; +} + +export const LendMobileCard = ({ currency, onDepositClicked }: LendMobileCardProps) => { + const { icon, name, ticker, issuerName } = currency; + + const { wallet, walletBalances } = useWallet(); + const { prices, pools } = usePools(); + const pool = pools?.[ticker]; + const price = prices?.[ticker]; + const balance: Balance | undefined = walletBalances?.[ticker]; + + const isPoor = !balance?.trustLine || isBalanceZero(balance.balanceLine.balance); + + return ( +
+
+ +
+

{name}

+

+ {ticker} • {issuerName} +

+
+
+ +
+
+

Balance

+

+ {pool ? formatAmount(pool.totalBalanceTokens) : } +

+

+ {!isNil(price) && !isNil(pool) && toDollarsFormatted(price, pool.totalBalanceTokens)} +

+
+
+

Supply APY

+

{pool ? formatAPY(pool.annualInterestRate) : }

+
+
+ +
+ {isPoor ? ( +
+ +
+ ) : ( + + )} +
+
+ ); +}; diff --git a/src/pages/_lend/LendPage.tsx b/src/pages/_lend/LendPage.tsx index ba787418..ee5f83d3 100644 --- a/src/pages/_lend/LendPage.tsx +++ b/src/pages/_lend/LendPage.tsx @@ -8,6 +8,7 @@ import { usePools } from '@contexts/pool-context'; import { contractId } from '@contracts/loan_manager'; import { CURRENCY_BINDINGS_ARR, type CurrencyBinding } from 'src/currency-bindings'; import { DepositModal } from './DepositModal'; +import { LendMobileCard } from './LendMobileCard'; import { LendableAsset } from './LendableAsset'; const links = [ @@ -41,15 +42,26 @@ const LendPage = () => {

Lend Assets

- +
{CURRENCY_BINDINGS_ARR.map((currency) => ( - openDepositModal(currency)} /> ))} -
+
+
+ + {CURRENCY_BINDINGS_ARR.map((currency) => ( + openDepositModal(currency)} + /> + ))} +
+