Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 146 additions & 0 deletions typescript/agentkit/src/action-providers/aave/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# Aave Action Provider

This directory contains the **AaveActionProvider** implementation, which provides actions to interact with the **Aave V3 Protocol** for lending and borrowing operations.

## Directory Structure

```
aave/
├── aaveActionProvider.ts # Main provider with Aave functionality
├── aaveActionProvider.test.ts # Test file for Aave provider
├── schemas.ts # Aave action schemas
├── constants.ts # Contract addresses and ABIs
├── index.ts # Main exports
└── README.md # This file
```

## Actions

### Supply

`supply` - Supply assets to Aave as collateral

- **assetId**: The asset to supply (`weth`, `usdc`, `cbeth`, `wsteth`, `dai`, `usdt`)
- **amount**: The amount of tokens to supply in human-readable format

Example: "Supply 1 WETH to Aave"

### Withdraw

`withdraw` - Withdraw previously supplied assets from Aave

- **assetId**: The asset to withdraw
- **amount**: The amount of tokens to withdraw

Example: "Withdraw 1000 USDC from Aave"

### Borrow

`borrow` - Borrow assets from Aave against your collateral

- **assetId**: The asset to borrow (`weth`, `usdc`, `dai`, `usdt`)
- **amount**: The amount of tokens to borrow
- **interestRateMode**: Either `stable` or `variable` (default: variable)

Example: "Borrow 500 USDC with variable interest rate"

### Repay

`repay` - Repay borrowed assets to Aave

- **assetId**: The asset to repay
- **amount**: The amount of tokens to repay
- **interestRateMode**: The interest rate mode of the debt

Example: "Repay 500 USDC variable rate debt"

### Get User Data

`get_user_data` - Get the user's account summary from Aave

Returns:
- Total collateral in USD
- Total debt in USD
- Available borrows in USD
- Loan-to-Value ratio
- Liquidation threshold
- Health factor with status indicator

## Network Support

The Aave provider supports:
- **Base Mainnet** (`base-mainnet`)
- **Ethereum Mainnet** (`ethereum-mainnet`)

## Supported Assets

| Asset | Symbol | Base | Ethereum |
|-------|--------|------|----------|
| Wrapped ETH | WETH | ✅ | ✅ |
| USD Coin | USDC | ✅ | ✅ |
| Coinbase Wrapped ETH | cbETH | ✅ | ✅ |
| Wrapped stETH | wstETH | ✅ | ✅ |
| DAI Stablecoin | DAI | ✅ | ✅ |
| Tether USD | USDT | ✅ | ✅ |

## Important Notes

### Health Factor

The health factor represents the safety of your position:

| Health Factor | Status |
|---------------|--------|
| > 2.0 | ✅ Very Safe |
| 1.5 - 2.0 | 🟢 Safe |
| 1.1 - 1.5 | 🟡 Moderate Risk |
| 1.0 - 1.1 | 🟠 High Risk |
| < 1.0 | 🔴 Liquidation Risk |

### Interest Rate Modes

- **Variable**: Rate changes based on market supply/demand
- **Stable**: Fixed rate (may be higher than variable)

### Gas Considerations

- Supply and repay require token approval before the transaction
- All transactions require sufficient ETH for gas

## Example Usage

```typescript
import { aaveActionProvider } from "@coinbase/agentkit";

const aave = aaveActionProvider();

// Supply collateral
await aave.supply(wallet, { assetId: "weth", amount: "1" });

// Check account status
await aave.getUserData(wallet, {});

// Borrow against collateral
await aave.borrow(wallet, {
assetId: "usdc",
amount: "1000",
interestRateMode: "variable"
});

// Repay debt
await aave.repay(wallet, {
assetId: "usdc",
amount: "1000",
interestRateMode: "variable"
});

// Withdraw collateral
await aave.withdraw(wallet, { assetId: "weth", amount: "1" });
```

## References

- [Aave V3 Documentation](https://docs.aave.com/developers/getting-started/readme)
- [Aave V3 on Base](https://docs.aave.com/developers/deployed-contracts/v3-mainnet/base)
- [Aave Risk Parameters](https://docs.aave.com/risk/asset-risk/risk-parameters)

Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
import { AaveActionProvider } from "./aaveActionProvider";
import {
AaveSupplySchema,
AaveWithdrawSchema,
AaveBorrowSchema,
AaveRepaySchema,
AaveGetUserDataSchema,
} from "./schemas";

describe("Aave Action Provider Input Schemas", () => {
describe("Supply Schema", () => {
it("should successfully parse valid supply input", () => {
const validInput = {
assetId: "weth",
amount: "1.5",
};
const result = AaveSupplySchema.safeParse(validInput);
expect(result.success).toBe(true);
});

it("should fail for invalid asset", () => {
const invalidInput = {
assetId: "invalid",
amount: "1.5",
};
const result = AaveSupplySchema.safeParse(invalidInput);
expect(result.success).toBe(false);
});

it("should fail for invalid amount format", () => {
const invalidInput = {
assetId: "weth",
amount: "not-a-number",
};
const result = AaveSupplySchema.safeParse(invalidInput);
expect(result.success).toBe(false);
});
});

describe("Withdraw Schema", () => {
it("should successfully parse valid withdraw input", () => {
const validInput = {
assetId: "usdc",
amount: "1000",
};
const result = AaveWithdrawSchema.safeParse(validInput);
expect(result.success).toBe(true);
});
});

describe("Borrow Schema", () => {
it("should successfully parse valid borrow input with variable rate", () => {
const validInput = {
assetId: "usdc",
amount: "500",
interestRateMode: "variable",
};
const result = AaveBorrowSchema.safeParse(validInput);
expect(result.success).toBe(true);
});

it("should successfully parse valid borrow input with stable rate", () => {
const validInput = {
assetId: "weth",
amount: "0.5",
interestRateMode: "stable",
};
const result = AaveBorrowSchema.safeParse(validInput);
expect(result.success).toBe(true);
});

it("should fail for invalid interest rate mode", () => {
const invalidInput = {
assetId: "usdc",
amount: "500",
interestRateMode: "invalid",
};
const result = AaveBorrowSchema.safeParse(invalidInput);
expect(result.success).toBe(false);
});
});

describe("Repay Schema", () => {
it("should successfully parse valid repay input", () => {
const validInput = {
assetId: "usdc",
amount: "500",
interestRateMode: "variable",
};
const result = AaveRepaySchema.safeParse(validInput);
expect(result.success).toBe(true);
});
});

describe("GetUserData Schema", () => {
it("should successfully parse empty input", () => {
const validInput = {};
const result = AaveGetUserDataSchema.safeParse(validInput);
expect(result.success).toBe(true);
});
});
});

describe("Aave Action Provider", () => {
let actionProvider: AaveActionProvider;

beforeEach(() => {
actionProvider = new AaveActionProvider();
});

describe("constructor", () => {
it("should create an instance", () => {
expect(actionProvider).toBeDefined();
expect(actionProvider).toBeInstanceOf(AaveActionProvider);
});
});

describe("supportsNetwork", () => {
it("should return true for base-mainnet", () => {
expect(
actionProvider.supportsNetwork({
protocolFamily: "evm",
networkId: "base-mainnet",
}),
).toBe(true);
});

it("should return true for ethereum-mainnet", () => {
expect(
actionProvider.supportsNetwork({
protocolFamily: "evm",
networkId: "ethereum-mainnet",
}),
).toBe(true);
});

it("should return false for unsupported networks", () => {
expect(
actionProvider.supportsNetwork({
protocolFamily: "evm",
networkId: "polygon-mainnet",
}),
).toBe(false);
});

it("should return false for non-EVM networks", () => {
expect(
actionProvider.supportsNetwork({
protocolFamily: "solana",
networkId: "solana-mainnet",
}),
).toBe(false);
});
});
});

Loading