How to Monitor Borrowers on Aave Using Streams and Functions

·

This guide demonstrates how to leverage QuickNode’s Streams and Functions to build a system that monitors Aave V3 borrowers' health factors. The process involves:

  1. Setting up a Stream to capture real-time borrowing events.
  2. Creating a Function to process these events, extract borrower addresses and health factors, and store data in QuickNode’s Key-Value Store API.

Designed for developers, this tutorial provides a step-by-step approach to blockchain data processing with serverless infrastructure.


Overview

Managing blockchain infrastructure can be complex. QuickNode’s Functions simplifies this by offering serverless solutions for deploying pre-built or custom logic without self-hosting.

In this guide, you’ll learn to:


Prerequisites


Step 1: Setting Up a Stream

Stream Configuration:

function main(stream) {
  try {
    const AAVE_V3_POOL_ADDRESS = '0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2'.toLowerCase();
    const BORROW_FUNCTION_SIGNATURE = '0xa415bcad'; // borrow() signature
    const filteredList = stream.data[0].filter(tx => 
      tx.to?.toLowerCase() === AAVE_V3_POOL_ADDRESS && 
      tx.input.startsWith(BORROW_FUNCTION_SIGNATURE)
    );
    return filteredList.length > 0 ? { 
      borrowers: filteredList.map(tx => ({ 
        block: parseInt(tx.blockNumber, 16), 
        borrower: tx.from 
      })) 
    } : { 
      block: parseInt(stream.data[0][0].blockNumber, 16), 
      message: "No borrow transactions found in this block." 
    };
  } catch (e) {
    return { error: e.message };
  }
}

Key Actions:


Step 2: Creating the Function

Function Code:

const ethers = require('ethers');
const RPC_URL = "YOUR_RPC_URL";
const WEBHOOK_URL = "YOUR_WEBHOOK_URL";
const AAVE_V3_POOL_ABI = [{
  "inputs": [{ "type": "address", "name": "user" }],
  "name": "getUserAccountData",
  "outputs": [{ "name": "healthFactor", "type": "uint256" }],
  "stateMutability": "view",
  "type": "function"
}];

let provider, aavePool;
function initializeContract() {
  provider = new ethers.JsonRpcProvider(RPC_URL);
  aavePool = new ethers.Contract('0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2', AAVE_V3_POOL_ABI, provider);
}

async function convertToHealthFactor(address) {
  const data = await aavePool.getUserAccountData(address);
  return ethers.formatUnits(data.healthFactor, 18);
}

async function main(params) {
  initializeContract();
  const borrowers = params.data?.borrowers || [];
  const processed = [];
  for (const { borrower } of borrowers) {
    const healthFactor = await convertToHealthFactor(borrower);
    await qnLib.qnAddListItem(`borrowers-AAVE_V3`, borrower);
    await qnLib.qnAddSet(`borrower-${borrower}`, healthFactor);
    processed.push({ borrower, healthFactor });
  }
  await sendToWebhook({ borrowers: processed });
  return { message: `Processed ${processed.length} borrowers.` };
}

Key Features:


Step 3: Testing the Key-Value Store

Retrieve stored borrower data via REST API:

curl -X GET "https://api.quicknode.com/kv/rest/v1/lists/borrowers-AAVE_V3" \
  -H "x-api-key: YOUR_API_KEY"

Sample Response:

{
  "data": {
    "items": ["0x123...", "0x456..."]
  }
}

Fetch a borrower’s health factor:

curl -X GET "https://api.quicknode.com/kv/rest/v1/sets/borrower-0x123" \
  -H "x-api-key: YOUR_API_KEY"

Output:

{ "data": { "value": "1.85" } }

FAQs

1. What is a health factor in Aave?

The health factor measures a borrower’s collateralization ratio. If it drops below 1, the position can be liquidated.

2. Can I monitor multiple blockchains?

Yes! QuickNode supports Ethereum, Optimism, Base, and more.

3. How often does the Function run?

It triggers only when a borrow event occurs, saving compute costs.

4. Can I extend this system?

Absolutely! Add:


Conclusion

By combining QuickNode Streams, Functions, and Key-Value Store, you’ve built an automated monitoring system for Aave borrowers. This scalable solution eliminates server management, letting you focus on real-time data logic.

👉 Explore more QuickNode guides

Feedback? Let us know how we can improve!