Learn how to fetch and monitor user positions on Aave v4.
Each user position captures a user’s activity within a Spoke, simplifying health and performance tracking.
User position data provides comprehensive information about a user's lending and borrowing activity on a specific spoke, including:
Identification: id, user, spoke, creation timestamp
Position balances: supplied amounts, collateral amounts, debt amounts, net balances
Yield information: supply APY, borrow APY, net APY, net interests
Risk metrics: health factor, user risk premium breakdown, liquidation price, borrowing power
Performance data: net balance percentage changes over time
- TypeScript
- GraphQL
- Solidity
The following TypeScript interfaces illustrate the core UserPosition type:
interface UserPosition { __typename: "UserPosition"; id: UserPositionId; user: EvmAddress; createdAt: Date; spoke: Spoke; totalSupplied: ExchangeAmountWithChange; totalCollateral: ExchangeAmountWithChange; totalDebt: ExchangeAmountWithChange; netBalance: ExchangeAmountWithChange; netCollateral: ExchangeAmountWithChange; netApy: PercentNumber; netSupplyApy: PercentNumberWithChange; netBorrowApy: PercentNumberWithChange; netAccruedInterest: ExchangeAmount; healthFactor: HealthFactorWithChange; riskPremium: UserPositionRiskPremium | null; liquidationPrice: ExchangeAmount | null; borrowingPower: ExchangeAmount; canUpdateDynamicConfig: boolean; netBalancePercentChange: PercentNumber; averageCollateralFactor: PercentNumber;}
See the Spoke Data Structure for more details.
Fetch all user positions with filtering and ordering options.
- React
- TypeScript
- GraphQL
- Solidity
Use the useUserPositions hook to fetch positions for a given user address.
import { type UserPositionsRequest, useUserPositions } from "@aave/react";
function UserPositionsList({ request }: { request: UserPositionsRequest }) { const { data, loading, error } = useUserPositions(request);
if (loading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
return ( <div> {data.map((position) => ( <div key={position.id}> <h3>Position on {position.spoke.name}</h3> <p>Chain: {position.spoke.chain.name}</p> </div> ))} </div> );}
You can filter positions by the following criteria:
import { evmAddress, chainId } from "@aave/react";
const request: UserPositionsRequest = { user: evmAddress("0x456…"), filter: { chainIds: [chainId(1)], },};
And you can sort positions as follows:
import { OrderDirection } from "@aave/react";
const request: UserPositionsRequest = { user: evmAddress("0x456…"), filter: { }, orderBy: { balance: OrderDirection.Asc },};
Finally, you can specify a different time window or currency for the data.
import { evmAddress, chainId, TimeWindow } from "@aave/react";
const { data, error, loading } = useUserPositions({ user: evmAddress("0x456…"), filter: { }, timeWindow: TimeWindow.LastWeek,});
Fetching a Single Position
Fetch a specific user position.
- React
- TypeScript
- GraphQL
- Solidity
Use the useUserPosition hook to fetch a specific user position.
import { type UserPositionRequest, useUserPosition } from "@aave/react";
function UserPositionDetail({ request }: { request: UserPositionRequest }) { const { data, loading, error } = useUserPosition(request);
if (loading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
if (!data) return <div>Position not found</div>;
return ( <div> <h2>Position {data.id}</h2> <p>Net Balance: {data.netBalance.amount.value.toDisplayString(2)}</p> <p>Health Factor: {data.healthFactor.value.toFixed(2)}</p> </div> );}
See below for examples of UserPositionRequest objects.
import { userPositionId } from "@aave/react";
const request: UserPositionRequest = { id: userPositionId(params.id), };
And you can specify a different time window or currency for the data.
import { TimeWindow } from "@aave/react";
const { data, error, loading } = useUserPosition({ timeWindow: TimeWindow.LastWeek,});
User supply data provides detailed information about individual user supplies within a spoke, including:
Reserve details: token information, supply APY, lending limits
Position amounts: supplied shares, earned amounts, and token details
Collateral status: whether the supply is used as collateral
Performance metrics: earned interest over time
The following TypeScript interfaces illustrate the UserSupplyItem type:
interface UserSupplyItem { __typename: "UserSupplyItem"; id: UserSupplyItemId; reserve: Reserve; principal: Erc20Amount; withdrawable: Erc20Amount; interest: Erc20Amount; isCollateral: boolean;}
See the Reserve Data Structure for more details.
Fetch user supplies within a specific spoke.
- React
- TypeScript
- GraphQL
- Solidity
Use the useUserSupplies hook to fetch user supplies for a user.
import { type UserSuppliesRequest, useUserSupplies } from "@aave/react";
function UserSuppliesList({ request }: { request: UserSuppliesRequest }) { const { data, loading, error } = useUserSupplies(request);
if (loading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
return ( <div> {data.map((supply) => ( <div key={supply.id}> <h3>{supply.reserve.asset.underlying.info.name}</h3> <p>Amount: {supply.withdrawable.amount.value.toDisplayString(2)}</p> </div> ))} </div> );}
See below for examples of UserSuppliesRequest objects.
const request: UserSuppliesRequest = { query: { userPositionId: position.id, },};
Sort user supplies by asset name, amount, or supply APY.
import { OrderDirection } from "@aave/react";
const request: UserSuppliesRequest = { query: { }, orderBy: { assetName: OrderDirection.Asc },};
Include zero-value entries for all other supply reserves available on the same spoke, typically ordered by descending amount.
import { OrderDirection } from "@aave/react";
const request: UserSuppliesRequest = { query: { }, includeZeroBalances: true, orderBy: { amount: OrderDirection.Desc },};
Finally, you can specify a different time window or currency for the data.
import { TimeWindow } from "@aave/react";
const { data, error, loading } = useUserSupplies({ query: { }, timeWindow: TimeWindow.LastWeek,});
User borrow data provides detailed information about individual borrow positions within a spoke, including:
Reserve details: token information, borrow APY, borrowing limits
Position amounts: borrowed amounts, repaid amounts, and token details
Debt tracking: outstanding debt and payment history
Performance metrics: interest owed and payment progress
The following TypeScript interfaces illustrate the UserBorrowItem type:
interface UserBorrowItem { __typename: "UserBorrowItem"; id: UserBorrowItemId; reserve: Reserve; principal: Erc20Amount; debt: Erc20Amount; interest: Erc20Amount;}
See the Reserve Data Structure for more details.
Fetch user borrows within a specific spoke.
- React
- TypeScript
- GraphQL
- Solidity
Use the useUserBorrows hook to fetch borrow positions for a user.
import { type UserBorrowsRequest, useUserBorrows } from "@aave/react";
function UserBorrowsList({ request }: { request: UserBorrowsRequest }) { const { data, loading, error } = useUserBorrows(request);
if (loading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
return ( <div> {data.map((borrow) => ( <div key={borrow.id}> <h3>{borrow.reserve.asset.underlying.info.name}</h3> <p>Amount: {borrow.debt.amount.value.toDisplayString(2)}</p> </div> ))} </div> );}
See below for examples of UserBorrowsRequest objects.
const request: UserBorrowsRequest = { query: { userPositionId: position.id, },};
Sort user borrows by asset name, amount, or borrow APY.
import { OrderDirection } from "@aave/react";
const request: UserBorrowsRequest = { query: { }, orderBy: { assetName: OrderDirection.Asc },};
Finally, you can specify a different time window or currency for the data.
import { TimeWindow } from "@aave/react";
const { data, error, loading } = useUserBorrows({ query: { }, timeWindow: TimeWindow.LastWeek,});
Include zero-value entries for all other borrow reserves available on the same spoke, typically ordered by descending amount.
import { OrderDirection } from "@aave/react";
const { data, error, loading } = useUserBorrows({ query: { }, includeZeroBalances: true, orderBy: { amount: OrderDirection.Desc },});
User summary data provides comprehensive information about a user's aggregated activity across all positions, including:
Position count: total number of positions held by the user
Portfolio totals: supplied amounts, collateral amounts, debt amounts, net balances
Yield information: calculated net APY across all positions
Risk metrics: lowest health factor across all positions
Performance data: net fee earned over time
The following TypeScript interfaces illustrate the UserSummary type:
interface UserSummary { __typename: "UserSummary"; totalPositions: number; netBalance: ExchangeAmountWithChange; totalCollateral: ExchangeAmount; totalSupplied: ExchangeAmount; totalDebt: ExchangeAmount; netApy: PercentNumber; netAccruedInterest: ExchangeAmount; lowestHealthFactor: BigDecimal | null;}
Fetch a comprehensive financial summary for a user across all their positions.
Use the useUserSummary hook to fetch the financial summary for a user.
import { type UserSummaryRequest, useUserSummary } from "@aave/react";
function UserSummaryDisplay({ request }: { request: UserSummaryRequest }) { const { data, loading, error } = useUserSummary(request);
if (loading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
return ( <div> <h2>Financial Summary</h2> <p>Total Positions: {data.totalPositions}</p> <p> Net Balance: {data.netBalance.current.symbol} {data.netBalance.current.value.toDisplayString(2)} </p> <p> Total Supplied: {data.totalSupplied.symbol} {data.totalSupplied.value.toDisplayString(2)} </p> <p> Total Debt: {data.totalDebt.symbol} {data.totalDebt.value.toDisplayString(2)} </p> <p>Net APY: {data.netApy.normalized.toFixed(2)}%</p> </div> );}
See below for examples of UserSummaryRequest objects.
import { evmAddress } from "@aave/react";
const request: UserSummaryRequest = { user: evmAddress("0x456…"),};
And you can specify a different time window or currency for the data.
import { TimeWindow } from "@aave/react";
const { data, error, loading } = useUserSummary({ user: evmAddress("0x456…"), timeWindow: TimeWindow.LastWeek,});
User summary history data provides detailed information about a user's activity changes over time, including:
Historical snapshots: portfolio state at different points in time
Portfolio metrics: net balance, borrows, supplies at each snapshot
Risk metrics: health factor changes over time
The following TypeScript interfaces illustrate the UserSummaryHistoryItem type:
interface UserSummaryHistoryItem { __typename: "UserSummaryHistoryItem"; netBalance: ExchangeAmount; borrows: ExchangeAmount; supplies: ExchangeAmount; healthFactor: BigDecimal | null; date: Date;}
Fetching User Summary History
Fetch historical financial data for a user over a specified time window.
Use the useUserSummaryHistory hook to fetch historical financial data for a user.
import { type UserSummaryHistoryRequest, useUserSummaryHistory,} from "@aave/react";
function UserSummaryHistory({ request,}: { request: UserSummaryHistoryRequest;}) { const { data, loading, error } = useUserSummaryHistory(request);
if (loading) return <div>Loading…</div>;
if (error) return <div>Error: {error.message}</div>;
return ( <div> <h2>Financial History</h2> {data.map((item) => ( <div key={item.date.toString()}> <p>Date: {item.date.toLocaleDateString()}</p> <p> Net Balance: {item.netBalance.symbol} {item.netBalance.value.toDisplayString(2)} </p> <p> Supplies: {item.supplies.symbol} {item.supplies.value.toDisplayString(2)} </p> <p> Borrows: {item.borrows.symbol} {item.borrows.value.toDisplayString(2)} </p> </div> ))} </div> );}
See below for examples of UserSummaryHistoryRequest objects.
import { evmAddress, TimeWindow } from "@aave/react";
const request: UserSummaryHistoryRequest = { user: evmAddress("0x456…"), window: TimeWindow.LastDay,};
Filter the history by specific spokes or chains.
import { evmAddress, TimeWindow } from "@aave/react";
const request: UserSummaryHistoryRequest = { user: evmAddress("0x456…"), window: TimeWindow.LastWeek, filter: { spokeId: spoke.id, },};
Specify a different currency for displaying fiat amounts.
import { Currency, evmAddress, TimeWindow } from "@aave/react";
const { data, error, loading } = useUserSummaryHistory({ user: evmAddress("0x456…"), window: TimeWindow.LastWeek, currency: Currency.Eur,});