# Aave V3 Incentive Programs

Aave reserves may offer additional incentives beyond base lending rates.

## Incentive Types

- **Supply Incentives**: Extra APR for supplying assets to reserves
- **Borrow Incentives**: APR discounts for borrowing from reserves
- **Conditional Incentives**: Bonus rewards requiring specific supply and borrow combinations

Each reserve’s `incentives` array contains all active incentive programs. The incentive data includes:

- APR bonuses/discounts with formatted percentages
- Reward token information (for Aave governance incentives)
- Claim links (for Merit programs)
- Conditional requirements (for complex incentives)

You can find the incentives associated with a reserve in the `incentives` array of the [Reserve](./data#reserve-structure) object.

```ts title="Reserve"
interface Reserve {
  // …
  incentives: ReserveIncentive[];
}
```

```ts title="ReserveIncentive"
type ReserveIncentive =
  | MeritSupplyIncentive
  | MeritBorrowIncentive
  | MeritBorrowAndSupplyIncentiveCondition
  | AaveSupplyIncentive
  | AaveBorrowIncentive
  | MerklSupplyIncentive
  | MerklBorrowIncentive
  | SupplyPointsIncentive
  | BorrowPointsIncentive;
```

These incentives come from two main sources:

- [Merit Programs](#merit-programs)
- [Aave Governance Rewards](#aave-governance-rewards)

### Merit Programs

[Third-party programs](https://apps.aavechan.com/merit) that provide extra APR rewards for specific lending activities. These require separate claiming through external platforms.

> [!WARNING]
> Merit programs are third-party initiatives. Aave Labs does not guarantee these
> programs and accepts no liability for third-party rewards.

```ts title="MeritSupplyIncentive"
interface MeritSupplyIncentive {
  __typename: "MeritSupplyIncentive";
  extraSupplyApr: PercentValue;
  claimLink: string;
}
```

```ts title="MeritBorrowIncentive"
interface MeritBorrowIncentive {
  __typename: "MeritBorrowIncentive";
  borrowAprDiscount: PercentValue;
  claimLink: string;
}
```

```ts title="MeritBorrowAndSupplyIncentiveCondition"
interface MeritBorrowAndSupplyIncentiveCondition {
  __typename: "MeritBorrowAndSupplyIncentiveCondition";
  extraApr: PercentValue;
  supplyToken: Currency;
  borrowToken: Currency;
  claimLink: string;
}
```

Where:

- `MeritSupplyIncentive`: Extra APR for supplying assets to reserves
- `MeritBorrowIncentive`: APR discounts for borrowing from reserves
- `MeritBorrowAndSupplyIncentiveCondition`: Extra APR for supplying and borrowing the specified pair of assets

For each of these types, a claim link to the [ACI Merit UI](https://apps.aavechan.com/merit) is provided.

### Aave Governance Rewards

Incentives set by Aave governance through the [RewardsController](../smart-contracts/incentives), typically distributed in AAVE tokens or other approved reward tokens.

```ts title="AaveSupplyIncentive"
interface AaveSupplyIncentive {
  __typename: "AaveSupplyIncentive";
  extraSupplyApr: PercentValue;
  rewardTokenAddress: EvmAddress;
  rewardTokenSymbol: string;
}
```

```ts title="AaveBorrowIncentive"
interface AaveBorrowIncentive {
  __typename: "AaveBorrowIncentive";
  borrowAprDiscount: PercentValue;
  rewardTokenAddress: EvmAddress;
  rewardTokenSymbol: string;
}
```

Where:

- `AaveSupplyIncentive`: Extra APR for supplying assets to reserves
- `AaveBorrowIncentive`: APR discounts for borrowing from reserves

In both cases, the reward token address and symbol are provided.

## Claim Merit Rewards

To check for and claim [Merit](https://apps.aavechan.com/merit) rewards, follow these steps.

### 1. Fetch the Claimable Rewards

First, determine if a user has claimable rewards. Use the `useUserRewards` hook in React, the `userRewards` action in TypeScript, or the `userRewards` query in GraphQL to fetch the user’s claimable rewards and the transaction to claim them.

<tabgroup>
<tab label="React">

```ts title="Loading State"
const { data, loading, error } = useUserRewards({
  user: EvmAddress,
  chainId: ChainId,
});
```

```ts title="React Suspense"
const { data } = useUserRewards({
  user: EvmAddress,
  chainId: ChainId,
  suspense: true,
});
```

</tab>
</tabgroup>
Fetch the user’s claimable rewards, optionally filtered by token.

<tabgroup>
<tab label="React">

```tsx title="Merit Rewards"
import { useUserRewards, evmAddress, chainId } from "@aave/react";

// …

const { data, loading, error } = useUserRewards({
  user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
  chainId: chainId(1),
});

if (loading) {
  return Loading claimable rewards…;
}

if (error) {
  return Error: {error.message};
}

// data: UserRewards | null
```

```tsx title="Filter by Token"
import { useUserRewards, evmAddress, chainId } from "@aave/react";

// …

const { data, loading, error } = useUserRewards({
  user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
  chainId: chainId(1),
  filter: {
    // Filter rewards by token address
    tokens: [evmAddress("0x000000000000000000000000000000000000000A")],
  },
});

if (loading) {
  return Loading claimable rewards…;
}

if (error) {
  return Error: {error.message};
}

// data: UserRewards | null
```

</tab>
<tab label="TypeScript">

```ts title="Merit Rewards"
import { userRewards } from "@aave/client/actions";
import { evmAddress, chainId } from "@aave/client";

import { client } from "./client";

const result = await userRewards(client, {
  user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
  chainId: chainId(1),
});

if (result.isErr()) {
  console.error("Merit claim rewards error:", result.error);
} else {
  // result.value: UserRewards | null
  console.log(result.value);
}
```

```ts title="Filter by Token"
import { userRewards } from "@aave/client/actions";
import { evmAddress, chainId } from "@aave/client";

import { client } from "./client";

const result = await userRewards(client, {
  user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
  chainId: chainId(1),
  filter: {
    // Filter rewards by token address
    tokens: [evmAddress("0x000000000000000000000000000000000000000A")],
  },
});

if (result.isErr()) {
  console.error("Merit claim rewards error:", result.error);
} else {
  // result.value: UserRewards | null
  console.log(result.value);
}
```

</tab>
<tab label="GraphQL">

```graphql title="Query"
query {
  userRewards(
    request: {
      user: "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"
      chainId: 1
      # Optional filter
      # filter: {
      #   tokens: ["0x000000000000000000000000000000000000000A"]
      # }
    }
  ) {
    chain
    claimable {
      amount {
        usdPerToken
        usd
        amount {
          value
          decimals
          raw
        }
      }
      currency {
        address
        imageUrl
        name
        symbol
        decimals
        chainId
      }
    }
    transaction {
      to
      from
      data
      value
      chainId
      operation
    }
  }
}
```

</tab>
</tabgroup>
The user has no claimable rewards if `data` is `null` in React, if `result.value` is `null` in TypeScript, or if the query result is `null` in GraphQL.

### 2. Claim Rewards

Finally, if the user has claimable rewards, they can claim them by sending the transaction.

- **React**: Use the `useSendTransaction` hook for the [wallet library of your choice](../getting-started/react#send-aave-transactions) to send `data.transaction`.
- **TypeScript**: Use `sendWith` for your [chosen wallet library](../getting-started/typescript#send-aave-transactions) to send the transaction.
- **GraphQL**: Send the `transaction` request directly using the wallet associated with the from address.

<tabgroup>
<tab label="React">

```tsx title="Viem"
import { useWalletClient } from "wagmi";
import { useUserRewards } from "@aave/react";
import { useSendTransaction } from "@aave/react/viem";

// …

const { data: walletClient } = useWalletClient();
const { data } = useUserRewards({
  // …
  suspense: true,
});

const [sendTransaction, sending] = useSendTransaction(walletClient);

// …

const execute = async () => {
  if (data !== null) {
    const result = await sendTransaction(data.transaction);

    if (result.isErr()) {
      console.error(result.error.message);
    } else {
      console.log("Merit claim rewards successful with hash:", result.value);
    }
  }
};
```

</tab>
<tab label="TypeScript">

```ts title="Viem"
import { userRewards } from "@aave/client/actions";
import { sendWith } from "@aave/client/viem";

import { client } from "./client";
import { wallet } from "./wallet";

const meritRewards = await userRewards(client, {
  // …
});

if (meritRewards.isErr()) {
  console.error(meritRewards.error);
  process.exit(1); // or eager return if in a function
}

if (!meritRewards.value) {
  console.log("No rewards to claim");
  process.exit(1); // or eager return if in a function
}

const result = await sendWith(wallet)(meritRewards.value.transaction);

if (result.isErr()) {
  console.error("Claiming Merit rewards failed:", result.error);
} else {
  console.log("Merit rewards claimed successfully:", result.value);
}
```

</tab>
<tab label="GraphQL">

Send `transaction` from the `from` wallet.

```json title="UserRewards"
{
  "data": {
    "userRewards": {
      "chain": 1,
      "claimable": [
        {
          "amount": {
            "usdPerToken": "1.000000000000000000",
            "usd": "1.00",
            "amount": {
              "value": "1.000000000000000000",
              "decimals": 18,
              "raw": "1000000000000000000"
            }
          },
          "currency": {
            "address": "0x000000000000000000000000000000000000000A",
            "name": "Example Token",
            "symbol": "EXAMPLE",
            "decimals": 18,
            "chainId": 1,
            "imageUrl": "https://example.com/image.png"
          }
        }
      ],
      "transaction": {
        "to": "0x000000000000000000000000000000000000000B",
        "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
        "data": "0x…",
        "value": "0",
        "chainId": 1,
        "operation": null
      }
    }
  }
}
```

</tab>
</tabgroup>
