Aave Looping with TypeScript

This guide demonstrates how to perform Aave looping operations using TypeScript and the Compass SDK. Aave looping is a strategy that allows you to leverage your position by borrowing against your collateral and reinvesting it to increase your exposure.

Prerequisites

Before you begin, make sure you have:

  1. Node.js installed on your system
  2. A Compass API key
  3. An Ethereum private key
  4. Access to an Ethereum RPC URL

Installation

First, install the required dependencies:

npm install @compass-labs/api-sdk dotenv viem

Implementation

Let’s break down the implementation into smaller, manageable parts.

1. Setting up the Environment

First, we’ll set up our environment and import the necessary dependencies:

import { CompassApiSDK } from "@compass-labs/api-sdk";
import dotenv from "dotenv";
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains';
import { http, SendTransactionRequest } from 'viem';
import { createWalletClient } from 'viem';

// Load environment variables
dotenv.config();

const PRIVATE_KEY = process.env.PRIVATE_KEY as string;
const RPC_URL = process.env.RPC_URL as string;

2. Initializing SDK and Wallet

Next, we’ll initialize the Compass SDK and set up our wallet client:

const initializeSDKAndWallet = () => {
    // Initialize the Compass SDK with your API key
    const compassApiSDK = new CompassApiSDK({
        apiKeyAuth: process.env.COMPASS_API_KEY,
    });

    // Create an account from your private key
    const account = privateKeyToAccount(`0x${PRIVATE_KEY}`);

    // Initialize the wallet client
    const walletClient = createWalletClient({
        account,
        chain: mainnet,
        transport: http(RPC_URL as string),
    });

    return { compassApiSDK, account, walletClient };
};

3. Getting Authorization

Then, we’ll handle the authorization process:

const getAuthorization = async (
    compassApiSDK: CompassApiSDK,
    account: any,
    walletClient: any
) => {
    // Get authorization for transaction batching
    const auth = await compassApiSDK.transactionBatching.authorization({
        chain: "ethereum:mainnet",
        sender: account.address,
    });

    // Sign the authorization
    const signedAuth = await walletClient.signAuthorization({
        account,
        address: auth.address as `0x${string}`,
    });

    return signedAuth;
};

4. Creating the Aave Loop Transaction

Now, we’ll create the Aave looping transaction:

const createLoopingTransaction = async (
    compassApiSDK: CompassApiSDK,
    account: any,
    signedAuth: any
) => {
    return await compassApiSDK.transactionBatching.aaveLoop({
        chain: "ethereum:mainnet",
        sender: account.address,
        signedAuthorization: {
            nonce: signedAuth.nonce,
            address: signedAuth.address,
            chainId: signedAuth.chainId,
            r: signedAuth.r,
            s: signedAuth.s,
            yParity: signedAuth.yParity as number,
        },
        collateralToken: "USDC",    // Token to use as collateral
        borrowToken: "WETH",        // Token to borrow
        initialCollateralAmount: 10, // Amount of collateral to start with
        multiplier: 2.0,            // Leverage multiplier
        maxSlippagePercent: 1,      // Maximum allowed slippage
        loanToValue: 80,            // Loan-to-value ratio
    });
};

5. Putting It All Together

Finally, here’s how we combine all the pieces:

const main = async () => {
    try {
        // Initialize SDK and wallet
        const { compassApiSDK, account, walletClient } = initializeSDKAndWallet();

        // Get authorization
        const signedAuth = await getAuthorization(compassApiSDK, account, walletClient);

        // Create the looping transaction
        const loopingTx = await createLoopingTransaction(compassApiSDK, account, signedAuth);

        // Send the transaction
        const tx = await walletClient.sendTransaction(loopingTx as unknown as SendTransactionRequest);
        console.log("Transaction hash:", tx);
    } catch (error) {
        console.error("Error executing Aave loop:", error);
    }
};

main();

Environment Setup

Create a .env file in your project root with the following variables:

COMPASS_API_KEY=your_compass_api_key
PRIVATE_KEY=your_ethereum_private_key_without_0x
RPC_URL=your_ethereum_rpc_url

Understanding the Parameters

The aaveLoop function accepts several important parameters:

  • chain: The blockchain network to use (e.g., “ethereum:mainnet”)
  • sender: Your wallet address
  • collateralToken: The token you want to use as collateral (e.g., “USDC”)
  • borrowToken: The token you want to borrow (e.g., “WETH”)
  • initialCollateralAmount: The amount of collateral to start with
  • multiplier: The leverage multiplier (e.g., 2.0 for 2x leverage)
  • maxSlippagePercent: Maximum allowed slippage for the transactions
  • loanToValue: The loan-to-value ratio for the position

Security Considerations

  1. Never commit your .env file to version control
  2. Keep your private key secure and never share it
  3. Use appropriate slippage settings to protect against price movements
  4. Monitor your loan-to-value ratio to avoid liquidation

Next Steps

  • Monitor your position regularly
  • Set up alerts for significant price movements
  • Consider implementing automatic health factor monitoring
  • Plan an exit strategy for your leveraged position

Error Handling

For production environments, you might want to add more specific error handling:

const executeAaveLoop = async () => {
    try {
        const { compassApiSDK, account, walletClient } = initializeSDKAndWallet();
        
        // Authorization
        try {
            const signedAuth = await getAuthorization(compassApiSDK, account, walletClient);
        } catch (error) {
            console.error("Authorization failed:", error);
            throw new Error("Failed to get authorization");
        }

        // Transaction creation
        try {
            const loopingTx = await createLoopingTransaction(compassApiSDK, account, signedAuth);
        } catch (error) {
            console.error("Failed to create looping transaction:", error);
            throw new Error("Transaction creation failed");
        }

        // Transaction execution
        try {
            const tx = await walletClient.sendTransaction(loopingTx as unknown as SendTransactionRequest);
            return tx;
        } catch (error) {
            console.error("Transaction execution failed:", error);
            throw new Error("Failed to execute transaction");
        }
    } catch (error) {
        console.error("Aave looping operation failed:", error);
        throw error;
    }
};