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
58 changes: 58 additions & 0 deletions examples/supply/src/MarketSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { type ChainId, type Market, useAaveMarkets } from '@aave/react';
import { useEffect } from 'react';

interface MarketSelectorProps {
chainId: ChainId;
onChange: (market: Market) => void;
}

export function MarketSelector({
chainId,
onChange: onMarketSelect,
}: MarketSelectorProps) {
const { data: markets } = useAaveMarkets({
chainIds: [chainId],
suspense: true,
});

useEffect(() => {
if (markets.length > 0) {
onMarketSelect(markets[0]);
}
}, [markets, onMarketSelect]);

const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const selectedMarket = markets.find(
(market) => market.address === event.target.value,
);
if (selectedMarket) {
onMarketSelect(selectedMarket);
}
};

if (markets.length === 0) {
return <p style={{ marginBottom: '5px' }}>No markets found</p>;
}

return (
<label>
<strong style={{ display: 'block' }}>Market:</strong>
<select
onChange={handleChange}
disabled={markets.length === 1}
style={{ padding: '8px', width: '100%' }}
>
{markets.map((market) => (
<option key={market.address} value={market.address}>
{market.name} - ${market.totalMarketSize}
</option>
))}
</select>
<small style={{ color: '#666' }}>
{markets.length === 1
? 'Only one market found'
: 'Select the market you want to supply to'}
</small>
</label>
);
}
40 changes: 40 additions & 0 deletions examples/supply/src/ReserveSelector.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import type { Reserve } from '@aave/react';

interface ReserveSelectorProps {
children?: React.ReactNode;
reserves: Reserve[];
onChange: (reserve: Reserve) => void;
}

export function ReserveSelector({
children,
reserves,
onChange,
}: ReserveSelectorProps) {
const handleChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
const selectedReserve = reserves.find(
(reserve) => reserve.underlyingToken.address === event.target.value,
);
if (selectedReserve) {
onChange(selectedReserve);
}
};

return (
<label style={{ marginBottom: '5px' }}>
<strong style={{ display: 'block' }}>Reserve:</strong>
<select onChange={handleChange} style={{ padding: '8px', width: '100%' }}>
{reserves.map((reserve) => (
<option
key={reserve.underlyingToken.address}
value={reserve.underlyingToken.address}
>
{reserve.underlyingToken.symbol} - APY:{' '}
{reserve.supplyInfo.apy.value}%
</option>
))}
</select>
{children}
</label>
);
}
102 changes: 102 additions & 0 deletions examples/supply/src/SupplyForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import {
bigDecimal,
errAsync,
evmAddress,
type Reserve,
useSupply,
} from '@aave/react';
import { useSendTransaction } from '@aave/react/viem';
import { useState } from 'react';
import type { WalletClient } from 'viem';

interface SupplyFormProps {
reserve: Reserve;
walletClient: WalletClient;
}

export function SupplyForm({ reserve, walletClient }: SupplyFormProps) {
const [amount, setAmount] = useState<string>('');
const [status, setStatus] = useState<string>('');

const [supply, supplying] = useSupply();
const [sendTransaction, sending] = useSendTransaction(walletClient);

const loading = supplying.loading || sending.loading;
const error = supplying.error || sending.error;

const handleSupply = async () => {
if (!amount) {
setStatus('Please enter an amount');
return;
}

const result = await supply({
chainId: reserve.market.chain.chainId,
market: reserve.market.address,
amount: {
erc20: {
currency: reserve.underlyingToken.address,
value: bigDecimal(amount),
},
},
supplier: evmAddress(walletClient.account!.address),
}).andThen((plan) => {
switch (plan.__typename) {
case 'TransactionRequest':
setStatus('Sending transaction...');
return sendTransaction(plan);

case 'ApprovalRequired':
setStatus('Approval required. Sending approval transaction...');

return sendTransaction(plan.approval).andThen(() => {
setStatus('Approval sent. Now sending supply transaction...');

return sendTransaction(plan.originalTransaction);
});

case 'InsufficientBalanceError':
setStatus(
`Insufficient balance: ${plan.available.value} ${reserve.underlyingToken.symbol}`,
);
return errAsync(
new Error(`Insufficient balance: ${plan.required.value}`),
);
}
});

if (result.isOk()) {
setStatus('Supply successful!');
}
};

return (
<div>
<label
style={{
marginBottom: '5px',
}}
>
<strong style={{ display: 'block' }}>Amount:</strong>
<input
disabled={loading}
type='number'
onChange={(e) => setAmount(e.target.value)}
style={{ width: '100%', padding: '8px' }}
placeholder='Amount to supply (in token units)'
/>
<small style={{ color: '#666' }}>
Human-friendly amount (e.g. 1.23, 4.56, 7.89)
</small>
</label>

<button type='button' disabled={loading} onClick={handleSupply}>
Supply
</button>

{status && <p style={{ marginBottom: '10px' }}>{status}</p>}

{error && <p style={{ color: '#f44336' }}>Error: {error.toString()}</p>}
</div>
);
}
11 changes: 4 additions & 7 deletions packages/react/src/markets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,16 @@ export function useAaveMarket(

export function useAaveMarket({
suspense = false,
address,
chainId,
user,
borrowsOrderBy = defaultMarketReservesRequestOrderBy,
suppliesOrderBy = defaultMarketReservesRequestOrderBy,
...request
}: UseAaveMarketArgs & {
suspense?: boolean;
}): SuspendableResult<Market | null> {
return useSuspendableQuery({
document: MarketQuery,
variables: {
request: { address, chainId, user },
request,
borrowsOrderBy,
suppliesOrderBy,
},
Expand Down Expand Up @@ -96,17 +94,16 @@ export function useAaveMarkets(args: UseAaveMarketsArgs): ReadResult<Market[]>;

export function useAaveMarkets({
suspense = false,
chainIds,
user,
borrowsOrderBy = defaultMarketReservesRequestOrderBy,
suppliesOrderBy = defaultMarketReservesRequestOrderBy,
...request
}: UseAaveMarketsArgs & {
suspense?: boolean;
}): SuspendableResult<Market[]> {
return useSuspendableQuery({
document: MarketsQuery,
variables: {
request: { chainIds, user },
request,
borrowsOrderBy,
suppliesOrderBy,
},
Expand Down
6 changes: 2 additions & 4 deletions packages/react/src/misc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,16 +119,14 @@ export function useUsdExchangeRates(

export function useUsdExchangeRates({
suspense = false,
market,
underlyingTokens,
chainId,
...request
}: UseUsdExchangeRatesArgs & {
suspense?: boolean;
}): SuspendableResult<UsdExchangeRate[]> {
return useSuspendableQuery({
document: UsdExchangeRatesQuery,
variables: {
request: { market, underlyingTokens, chainId },
request,
},
suspense,
});
Expand Down
7 changes: 2 additions & 5 deletions packages/react/src/reserves.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,14 @@ export function useAaveReserve(

export function useAaveReserve({
suspense = false,
market,
underlyingToken,
chainId,
user,
...request
}: UseAaveReserveArgs & {
suspense?: boolean;
}): SuspendableResult<Reserve | null> {
return useSuspendableQuery({
document: ReserveQuery,
variables: {
request: { market, underlyingToken, chainId, user },
request,
},
suspense,
});
Expand Down
19 changes: 6 additions & 13 deletions packages/react/src/user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,14 @@ export function useUserSupplies(

export function useUserSupplies({
suspense = false,
markets,
user,
collateralsOnly,
orderBy,
...request
}: UseUserSuppliesArgs & {
suspense?: boolean;
}): SuspendableResult<MarketUserReserveSupplyPosition[]> {
return useSuspendableQuery({
document: UserSuppliesQuery,
variables: {
request: { markets, user, collateralsOnly, orderBy },
request,
},
suspense,
});
Expand Down Expand Up @@ -112,16 +109,14 @@ export function useUserBorrows(

export function useUserBorrows({
suspense = false,
markets,
user,
orderBy,
...request
}: UseUserBorrowsArgs & {
suspense?: boolean;
}): SuspendableResult<MarketUserReserveBorrowPosition[]> {
return useSuspendableQuery({
document: UserBorrowsQuery,
variables: {
request: { markets, user, orderBy },
request,
},
suspense,
});
Expand Down Expand Up @@ -164,16 +159,14 @@ export function useUserMarketState(

export function useUserMarketState({
suspense = false,
market,
user,
chainId,
...request
}: UseUserStateArgs & {
suspense?: boolean;
}): SuspendableResult<MarketUserState> {
return useSuspendableQuery({
document: UserMarketStateQuery,
variables: {
request: { market, user, chainId },
request,
},
suspense,
});
Expand Down
Loading