Overview
Aave is a lending protocol where users supply stablecoins to earn interest from borrowers, or borrow assets against their existing balance. This guide walks through integrating Aave V3 into a Next.js app with Dynamic embedded wallets. For the final code, see the GitHub repository.How it works
Users supply a stablecoin to earn yield — deposit USDC, earn USDC. Interest paid by borrowers flows back to suppliers proportionally. Borrowers must maintain enough collateral to keep their position healthy; if it falls below a minimum ratio, the position can be liquidated. APY is variable and adjusts based on market demand.Setup
Project setup
Follow the JS SDK Quickstart to initialize a Next.js app with Dynamic. Scaffold a Next.js app withcreate-next-app and mirror the provider wiring from the quickstart or the GitHub repository.
In the Dynamic dashboard, enable Ethereum under Chains & Networks, enable Embedded wallets under Wallets, and add your app’s origin under Security → Allowed Origins.
Install dependencies
Environment variables
.env.local
Initialize Dynamic
Createsrc/lib/dynamic.ts:
src/lib/dynamic.ts
Create the Aave client
src/lib/aave.ts
Configure providers
Createsrc/lib/providers.tsx. DynamicProvider owns the reactive auth state; InnerProviders accesses it via useUser() and useGetWalletAccounts() from @dynamic-labs-sdk/react-hooks, eliminating the need for manual useState and onEvent subscriptions:
src/lib/providers.tsx
Enable transaction simulation
Dynamic’s embedded wallets include built-in transaction previews. To enable, go to Developer Settings → Embedded Wallets → Dynamic in the dashboard and toggle on Show Confirmation UI and Transaction Simulation. Users will see a breakdown of assets transferred, estimated fees, and the contract address before confirming any Aave transaction.
Get the wallet client
All Aave operations require aWalletClient from viem. Obtain it from the JS SDK EVM account:
walletClient and the active chain ID into useTransactionOperations.
Core operations
The Aave SDK uses a plan-based pattern. Each operation (useSupply, useBorrow, etc.) returns a function that resolves to a transaction plan. The plan tells you what kind of transaction to send — a direct transaction, one that first needs a token approval, or a failure due to insufficient balance. useSendTransaction handles submitting the plan to the wallet.
Create src/lib/useTransactionOperations.ts:
src/lib/useTransactionOperations.ts
Reading market and position data
Use these hooks from@aave/react to fetch available markets and the user’s positions:
Wiring it together
Here is how the wallet client, operations hook, and data hooks connect in a component:src/components/MarketsInterface.tsx
Run the app
http://localhost:3000 to your allowed origins in the Dynamic dashboard under Developer Settings → CORS Origins.