Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/pages/_borrow/BorrowMobileCard.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="border-b-2 border-base-300 p-4 mb-6 bg-base-100">
<div className="flex items-center gap-3 mb-3">
<img src={icon} alt="" className="w-12 h-12" />
<div className="flex-1">
<h2 className="font-semibold text-xl tracking-tight">{name}</h2>
<p className="text-sm opacity-70">
{ticker} • {issuerName}
</p>
</div>
</div>

<div className="grid grid-cols-2 gap-4 mb-3">
<div>
<p className="text-sm opacity-70 mb-1">Available</p>
<p className="font-semibold text-lg">
{pool ? formatAmount(pool.availableBalanceTokens) : <Loading size="xs" />}
</p>
<p className="text-sm opacity-70">
{!isNil(price) && !isNil(pool) && toDollarsFormatted(price, pool.availableBalanceTokens)}
</p>
</div>
<div>
<p className="text-sm opacity-70 mb-1">Borrow APY</p>
<p className="font-semibold text-lg">{pool ? formatAPR(pool.annualInterestRate) : <Loading size="xs" />}</p>
</div>
</div>

<div className="flex flex-col gap-2">
{borrowDisabled ? (
<div className="tooltip w-full" data-tip={tooltip}>
<Button disabled={true} onClick={() => {}} className="">
Borrow
</Button>
</div>
) : (
<Button onClick={onBorrowClicked} className="w-full">
Borrow
</Button>
)}
</div>
</div>
);
};
18 changes: 15 additions & 3 deletions src/pages/_borrow/BorrowPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -44,15 +45,26 @@ const BorrowPage = () => {
<Card links={links}>
<div className="px-12 pb-12 pt-4">
<h1 className="text-2xl font-semibold mb-4 tracking-tight">Borrow Assets</h1>
<Table headers={['Asset', null, 'Ticker', 'Balance', 'Borrow APY', null]}>
<div className="block md:hidden">
{CURRENCY_BINDINGS_ARR.map((currency) => (
<BorrowableAsset
<BorrowMobileCard
key={currency.ticker}
currency={currency}
onBorrowClicked={() => openBorrowModal(currency)}
/>
))}
</Table>
</div>
<div className="hidden md:block">
<Table headers={['Asset', null, 'Ticker', 'Balance', 'Borrow APY', null]}>
{CURRENCY_BINDINGS_ARR.map((currency) => (
<BorrowableAsset
key={currency.ticker}
currency={currency}
onBorrowClicked={() => openBorrowModal(currency)}
/>
))}
</Table>
</div>
<StellarExpertLink className="mt-3" contractId={contractId} text="View Loan Manager contract" />
</div>
</Card>
Expand Down
69 changes: 69 additions & 0 deletions src/pages/_lend/LendMobileCard.tsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="border-b-2 border-base-300 p-4 mb-6 bg-base-100">
<div className="flex items-center gap-3 mb-3">
<img src={icon} alt="" className="w-12 h-12" />
<div className="flex-1">
<h2 className="font-semibold text-xl tracking-tight">{name}</h2>
<p className="text-sm opacity-70">
{ticker} • {issuerName}
</p>
</div>
</div>

<div className="grid grid-cols-2 gap-4 mb-3">
<div>
<p className="text-sm opacity-70 mb-1">Balance</p>
<p className="font-semibold text-lg">
{pool ? formatAmount(pool.totalBalanceTokens) : <Loading size="xs" />}
</p>
<p className="text-sm opacity-70">
{!isNil(price) && !isNil(pool) && toDollarsFormatted(price, pool.totalBalanceTokens)}
</p>
</div>
<div>
<p className="text-sm opacity-70 mb-1">Supply APY</p>
<p className="font-semibold text-lg">{pool ? formatAPY(pool.annualInterestRate) : <Loading size="xs" />}</p>
</div>
</div>

<div className="flex flex-col gap-2">
{isPoor ? (
<div className="tooltip w-full" data-tip={!wallet ? 'Connect a wallet first' : 'Not enough funds'}>
<Button disabled={true} onClick={() => {}} className="">
Deposit
</Button>
</div>
) : (
<Button onClick={onDepositClicked} className="w-full">
Deposit
</Button>
)}
</div>
</div>
);
};
18 changes: 15 additions & 3 deletions src/pages/_lend/LendPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down Expand Up @@ -41,15 +42,26 @@ const LendPage = () => {
<Card links={links}>
<div className="px-12 pb-12 pt-4">
<h1 className="text-2xl font-semibold mb-4 tracking-tight">Lend Assets</h1>
<Table headers={['Asset', null, 'Ticker', 'Balance', 'Supply APY', null]}>
<div className="block md:hidden">
{CURRENCY_BINDINGS_ARR.map((currency) => (
<LendableAsset
<LendMobileCard
key={currency.ticker}
currency={currency}
onDepositClicked={() => openDepositModal(currency)}
/>
))}
</Table>
</div>
<div className="hidden md:block">
<Table headers={['Asset', null, 'Ticker', 'Balance', 'Supply APY', null]}>
{CURRENCY_BINDINGS_ARR.map((currency) => (
<LendableAsset
key={currency.ticker}
currency={currency}
onDepositClicked={() => openDepositModal(currency)}
/>
))}
</Table>
</div>
<StellarExpertLink className="mt-3" contractId={contractId} text="View Loan Manager contract" />
</div>
</Card>
Expand Down