From 5f7175d7703f75cdac3df9da9c736f1a5cadc735 Mon Sep 17 00:00:00 2001 From: Mark Hinschberger Date: Thu, 17 Jul 2025 21:04:08 +0100 Subject: [PATCH 1/3] feat: user positions --- examples/user-positions/README.md | 3 + examples/user-positions/index.html | 14 ++ examples/user-positions/package.json | 22 ++ examples/user-positions/public/aave.svg | 1 + examples/user-positions/src/App.tsx | 243 ++++++++++++++++++++++ examples/user-positions/src/client.ts | 5 + examples/user-positions/src/main.tsx | 10 + examples/user-positions/src/vite-env.d.ts | 1 + examples/user-positions/tsconfig.json | 20 ++ examples/user-positions/vite.config.ts | 6 + 10 files changed, 325 insertions(+) create mode 100644 examples/user-positions/README.md create mode 100644 examples/user-positions/index.html create mode 100644 examples/user-positions/package.json create mode 100644 examples/user-positions/public/aave.svg create mode 100644 examples/user-positions/src/App.tsx create mode 100644 examples/user-positions/src/client.ts create mode 100644 examples/user-positions/src/main.tsx create mode 100644 examples/user-positions/src/vite-env.d.ts create mode 100644 examples/user-positions/tsconfig.json create mode 100644 examples/user-positions/vite.config.ts diff --git a/examples/user-positions/README.md b/examples/user-positions/README.md new file mode 100644 index 0000000..5a7b261 --- /dev/null +++ b/examples/user-positions/README.md @@ -0,0 +1,3 @@ +# query for user positions on aave v3 + +[![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/aave/aave-sdk/tree/main/examples/user-positions) diff --git a/examples/user-positions/index.html b/examples/user-positions/index.html new file mode 100644 index 0000000..f914789 --- /dev/null +++ b/examples/user-positions/index.html @@ -0,0 +1,14 @@ + + + + + + + + query for user positions on aave v3 + + +
+ + + diff --git a/examples/user-positions/package.json b/examples/user-positions/package.json new file mode 100644 index 0000000..f591fae --- /dev/null +++ b/examples/user-positions/package.json @@ -0,0 +1,22 @@ +{ + "name": "user-positions", + "description": "query for user positions on aave v3", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite" + }, + "dependencies": { + "@aave/react": "workspace:*", + "react": "^19.1.0", + "react-dom": "^19.1.0" + }, + "devDependencies": { + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react-swc": "^3.7.2", + "typescript": "^5.6.3", + "vite": "^5.4.9" + } +} diff --git a/examples/user-positions/public/aave.svg b/examples/user-positions/public/aave.svg new file mode 100644 index 0000000..f6f9113 --- /dev/null +++ b/examples/user-positions/public/aave.svg @@ -0,0 +1 @@ + diff --git a/examples/user-positions/src/App.tsx b/examples/user-positions/src/App.tsx new file mode 100644 index 0000000..7d3d790 --- /dev/null +++ b/examples/user-positions/src/App.tsx @@ -0,0 +1,243 @@ +import { AaveProvider, useUserSupplies, useUserBorrows, evmAddress, chainId, useAaveMarkets } from '@aave/react'; +import { client } from './client'; + +const user = evmAddress("0x58f2aA5b752E284C45894ab0D435d0D53A8794CC"); + +function UserPositions() { + const { data: markets, loading: marketsLoading } = useAaveMarkets({ + chainIds: [chainId(1), chainId(8453)], + }); + + console.log(markets); + + // Transform markets to extract address and chainId + const marketAddresses = markets?.map(market => ({ + address: market.address, + chainId: market.chain.chainId, + })) || []; + + const { data: userSupplies, loading: userSuppliesLoading } = useUserSupplies({ + markets: marketAddresses, + user, + }); + + const { data: userBorrows, loading: userBorrowsLoading } = useUserBorrows({ + markets: marketAddresses, + user, + }); + + if (userSuppliesLoading || userBorrowsLoading || marketsLoading) { + return

Loading positions...

; + } + + console.log("userSupplies", userSupplies); + console.log("userBorrows", userBorrows); + + return ( + <> +
+

👻 Aave V3 User Positions

+

Address: {user}

+
+ +
+

Supply Positions ({userSupplies?.length || 0})

+ + {userSupplies?.map((position, index) => ( +
+
+ {position.currency.symbol} +
+

+ {position.currency.name} ({position.currency.symbol}) +

+

+ {position.market.name} +

+
+
+ {position.market.chain.name} +
+

+ {position.market.chain.name} +

+

+ Chain ID: {position.market.chain.chainId} +

+
+
+
+ +
+
+

Balance

+

+ {parseFloat(position.balance.amount.value).toFixed(6)} {position.currency.symbol} +

+

+ ${parseFloat(position.balance.usd).toFixed(2)} USD +

+
+ +
+

Supply APY

+

+ {(parseFloat(position.apy.value) * 100).toFixed(2)}% +

+
+ +
+

Token Price

+

+ ${parseFloat(position.balance.usdPerToken).toLocaleString()} +

+
+ +
+

Collateral Status

+
+ + {position.canBeCollateral ? '✅ Can Collateralize' : '❌ Cannot Collateralize'} + + {position.isCollateral && ( + + 🔒 Used as Collateral + + )} +
+
+
+
+ ))} + + {userSupplies?.length === 0 && ( +

+ No supply positions found for this address. +

+ )} + +

Borrow Positions ({userBorrows?.length || 0})

+ + {userBorrows?.map((position, index) => ( +
+
+ {position.currency.symbol} +
+

+ {position.currency.name} ({position.currency.symbol}) +

+

+ {position.market.name} +

+
+
+ {position.market.chain.name} +
+

+ {position.market.chain.name} +

+

+ Chain ID: {position.market.chain.chainId} +

+
+
+
+ +
+
+

Debt Amount

+

+ {parseFloat(position.debt.amount.value).toFixed(6)} {position.currency.symbol} +

+

+ ${parseFloat(position.debt.usd).toFixed(2)} USD +

+
+ +
+

Borrow APY

+

+ {(parseFloat(position.apy.value) * 100).toFixed(2)}% +

+
+ +
+

Token Price

+

+ ${parseFloat(position.debt.usdPerToken).toLocaleString()} +

+
+ +
+

Borrow Type

+ + 📉 Borrowed Debt + +
+
+
+ ))} + + {userBorrows?.length === 0 && ( +

+ No borrow positions found for this address. +

+ )} +
+ + ); +} + +export function App() { + return ( + + + + ); +} diff --git a/examples/user-positions/src/client.ts b/examples/user-positions/src/client.ts new file mode 100644 index 0000000..3653cce --- /dev/null +++ b/examples/user-positions/src/client.ts @@ -0,0 +1,5 @@ +import { AaveClient, staging } from '@aave/react'; + +export const client = AaveClient.create({ + environment: staging, +}); diff --git a/examples/user-positions/src/main.tsx b/examples/user-positions/src/main.tsx new file mode 100644 index 0000000..216848b --- /dev/null +++ b/examples/user-positions/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; + +import { App } from './App'; + +createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/examples/user-positions/src/vite-env.d.ts b/examples/user-positions/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/examples/user-positions/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/user-positions/tsconfig.json b/examples/user-positions/tsconfig.json new file mode 100644 index 0000000..3ca84ac --- /dev/null +++ b/examples/user-positions/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "jsx": "react-jsx", + "module": "ESNext", + "moduleResolution": "Bundler", + "strict": true, + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "noEmit": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noImplicitReturns": true, + "skipLibCheck": true + }, + "include": ["src", "vite.config.ts"] +} diff --git a/examples/user-positions/vite.config.ts b/examples/user-positions/vite.config.ts new file mode 100644 index 0000000..0225812 --- /dev/null +++ b/examples/user-positions/vite.config.ts @@ -0,0 +1,6 @@ +import react from '@vitejs/plugin-react-swc'; +import { defineConfig } from 'vite'; + +export default defineConfig({ + plugins: [react()], +}); From 3dd4430db226bac808c12f8f296050b9ed06c7e5 Mon Sep 17 00:00:00 2001 From: Mark Hinschberger Date: Thu, 17 Jul 2025 21:10:07 +0100 Subject: [PATCH 2/3] chore: cleanup --- examples/user-positions/src/App.tsx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/examples/user-positions/src/App.tsx b/examples/user-positions/src/App.tsx index 7d3d790..da81cd0 100644 --- a/examples/user-positions/src/App.tsx +++ b/examples/user-positions/src/App.tsx @@ -1,16 +1,14 @@ -import { AaveProvider, useUserSupplies, useUserBorrows, evmAddress, chainId, useAaveMarkets } from '@aave/react'; +import { AaveProvider, useUserSupplies, useUserBorrows, evmAddress, chainId, useAaveMarkets, ZERO_ADDRESS } from '@aave/react'; import { client } from './client'; -const user = evmAddress("0x58f2aA5b752E284C45894ab0D435d0D53A8794CC"); +// TODO: change to your address or any address you want to query +const user = evmAddress("ZERO_ADDRESS"); function UserPositions() { const { data: markets, loading: marketsLoading } = useAaveMarkets({ chainIds: [chainId(1), chainId(8453)], }); - console.log(markets); - - // Transform markets to extract address and chainId const marketAddresses = markets?.map(market => ({ address: market.address, chainId: market.chain.chainId, @@ -30,9 +28,6 @@ function UserPositions() { return

Loading positions...

; } - console.log("userSupplies", userSupplies); - console.log("userBorrows", userBorrows); - return ( <>
From 26d99f85fde60884762e5508858847b8306cb356 Mon Sep 17 00:00:00 2001 From: Mark Hinschberger Date: Tue, 22 Jul 2025 09:28:42 +0100 Subject: [PATCH 3/3] Update examples/user-positions/src/App.tsx Co-authored-by: Cesare Naldi --- examples/user-positions/src/App.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/user-positions/src/App.tsx b/examples/user-positions/src/App.tsx index da81cd0..fcdcb12 100644 --- a/examples/user-positions/src/App.tsx +++ b/examples/user-positions/src/App.tsx @@ -2,7 +2,7 @@ import { AaveProvider, useUserSupplies, useUserBorrows, evmAddress, chainId, use import { client } from './client'; // TODO: change to your address or any address you want to query -const user = evmAddress("ZERO_ADDRESS"); +const user = evmAddress(ZERO_ADDRESS); function UserPositions() { const { data: markets, loading: marketsLoading } = useAaveMarkets({