# Withdraw Assets on Aave V3

Withdraw supplied assets from Aave V3 markets.

## Withdraw Assets

Users can withdraw assets from Aave markets using their previously supplied reserves.

When withdrawing assets from an Aave market, you can use the following methods:

| Method                | Description                                                   | Typical Scenario                                                           |
| --------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------- |
| **Direct Withdraw**   | Withdraw ERC-20 or native tokens directly to supplier wallet. | User withdraws supplied assets from their own wallet balance.              |
| **Another Recipient** | Withdraw supplied assets to another address.                  | User supplied with one wallet and wants to withdraw to a different wallet. |

To withdraw supplied assets from an Aave market, follow these steps.

### 1. Identify the Supply Position

First, determine which user supply position you want to withdraw assets from.

Given this `MarketUserReserveSupplyPosition` object:

```ts title="MarketUserReserveSupplyPosition"
const position: MarketUserReserveSupplyPosition = {
  __typename: "MarketUserReserveSupplyPosition",
  market: {
    __typename: "MarketInfo",
    address: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2",
    chain: { chainId: 1 },
    // …
  },
  currency: {
    __typename: "Currency",
    symbol: "WETH",
    name: "Wrapped Ether",
    address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // …
  },
  balance: {
    __typename: "TokenAmount",
    amount: {
      __typename: "DecimalValue",
      value: "5.0",
      raw: "5000000000000000000",
      decimals: 18,
      // …
    },
    // …
  },
  // …
};
```

That is tied to the following `Reserve` object.

```ts title="Reserve"
const reserve: Reserve = {
  __typename: "Reserve",
  market: {
    __typename: "MarketInfo",
    address: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2",
    chain: { chainId: 1 },
    // …
  },
  underlyingToken: {
    __typename: "Currency",
    symbol: "WETH",
    name: "Wrapped Ether",
    address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // …
  },
  acceptsNative: {
    __typename: "NativeCurrency",
    // …
  },
};
```

### 2. Prepare the Withdraw Execution Plan

Next, we can proceed with creating the execution plan for the withdraw operation.

Use the `useWithdraw` hook in React, the `withdraw` action in TypeScript, or the `withdraw` query in GraphQL to create the execution plan for withdrawing assets from a market reserve.

<tabgroup>
<tab label="React">

```tsx title="Withdraw ERC-20 Amount"
import { useWalletClient } from "wagmi";
import { useWithdraw, bigDecimal, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [withdraw, withdrawing] = useWithdraw();

const execute = async () => {
  const result = await withdraw({
    market: position.market.address,
    amount: {
      erc20: {
        currency: position.currency.address,
        value: {
          exact: bigDecimal(2), // 2 WETH
        },
      },
    },
    sender: evmAddress(walletClient!.account.address),
    chainId: position.market.chain.chainId,
  });

  // …
};
```

```tsx title="Withdraw Max ERC-20 Amount"
import { useWalletClient } from "wagmi";
import { useWithdraw, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [withdraw, withdrawing] = useWithdraw();

const execute = async () => {
  const result = await withdraw({
    market: position.market.address,
    amount: {
      erc20: {
        currency: position.currency.address,
        value: {
          max: true,
        },
      },
    },
    sender: evmAddress(walletClient!.account.address),
    chainId: position.market.chain.chainId,
  });

  // …
};
```

```tsx title="Withdraw to Another Recipient"
import { useWalletClient } from "wagmi";
import { useWithdraw, bigDecimal, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [withdraw, withdrawing] = useWithdraw();

const execute = async () => {
  const result = await withdraw({
    market: position.market.address,
    amount: {
      erc20: {
        currency: position.currency.address,
        value: {
          exact: bigDecimal(2), // 2 WETH
        },
      },
    },
    recipient: evmAddress("0x1234567890123456789012345678901234567890"),
    sender: evmAddress(walletClient!.account.address),
    chainId: position.market.chain.chainId,
  });

  // …
};
```

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

```ts title="Withdraw ERC-20 Amount"
import { withdraw } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

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

const result = await withdraw(client, {
  market: position.market.address,
  amount: {
    erc20: {
      currency: position.currency.address,
      value: {
        exact: bigDecimal(2), // 2 WETH
      },
    },
  },
  sender: evmAddress(wallet.account.address),
  chainId: position.market.chain.chainId,
});

// …
```

```ts title="Withdraw Max ERC-20 Amount"
import { withdraw } from "@aave/client/actions";
import { evmAddress } from "@aave/client";

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

const result = await withdraw(client, {
  market: position.market.address,
  amount: {
    erc20: {
      currency: position.currency.address,
      value: {
        max: true,
      },
    },
  },
  sender: evmAddress(wallet.account.address),
  chainId: position.market.chain.chainId,
});

// …
```

```ts title="Withdraw to Another Recipient"
import { withdraw } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

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

const result = await withdraw(client, {
  market: position.market.address,
  amount: {
    erc20: {
      currency: position.currency.address,
      value: {
        exact: bigDecimal(2), // 2 WETH
      },
    },
  },
  recipient: evmAddress("0x1234567890123456789012345678901234567890"),
  sender: evmAddress(wallet.account.address),
  chainId: position.market.chain.chainId,
});

// …
```

```ts title="Withdraw Native to Another Recipient"
import { withdraw } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

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

const result = await withdraw(client, {
  market: position.market.address,
  amount: {
    native: {
      value: { exact: bigDecimal(2) }, // 2 ETH
    },
  },
  recipient: evmAddress("0x1234567890123456789012345678901234567890"),
  sender: evmAddress(wallet.account.address),
  chainId: position.market.chain.chainId,
});

// …
```

```ts title="client.ts"
import { AaveClient } from "@aave/client";

export const client = AaveClient.create();
```

```ts title="wallet.ts"
import { createWalletClient, http, type Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

export const wallet = createWalletClient({
  account: privateKeyToAccount(process.env.PRIVATE_KEY as Hex),
  chain: mainnet,
  transport: http(),
});
```

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

```graphql title="Query"
query {
  withdraw(
    request: {
      market: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2"
      amount: {
        erc20: {
          currency: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          value: {
            exact: "2"
            # OR
            # max: true
          }
        }
        # OR if the reserve accepts native currency
        # native: {
        #   value: { exact: "2" }
        #   # OR
        #   # max: true
        # }
      }
      sender: "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"
      chainId: 1
      # OPTIONAL: if you want to withdraw to a different address
      # recipient: "0x1234567890123456789012345678901234567890"
    }
  ) {
    __typename
    ... on TransactionRequest {
      to
      from
      data
      value
      chainId
      operation
    }
    ... on ApprovalRequired {
      reason
      requiredAmount {
        value
        decimals
      }
      currentAllowance {
        value
        decimals
      }
      approval {
        to
        from
        data
        value
        chainId
        operation
      }
      originalTransaction {
        to
        from
        data
        value
        chainId
        operation
      }
    }
    ... on InsufficientBalanceError {
      required {
        value
        decimals
      }
      available {
        value
        decimals
      }
    }
  }
}
```

</tab>
</tabgroup>
If `Reserve.acceptsNative` is not `null`, you can choose to withdraw the assets as the chain’s native token.

<tabgroup>
<tab label="React">

```tsx title="Withdraw Exact Native Amount"
import { useWalletClient } from "wagmi";
import { useWithdraw, bigDecimal, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [withdraw, withdrawing] = useWithdraw();

const execute = async () => {
  const result = await withdraw({
    market: position.market.address,
    amount: {
      native: {
        value: { exact: bigDecimal(2) }, // 2 ETH
      },
    },
    sender: evmAddress(walletClient!.account.address),
    chainId: position.market.chain.chainId,
  });

  // …
};
```

```tsx title="Withdraw Max Native Amount"
import { useWalletClient } from "wagmi";
import { useWithdraw, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [withdraw, withdrawing] = useWithdraw();

const execute = async () => {
  const result = await withdraw({
    market: position.market.address,
    amount: {
      native: {
        value: { max: true },
      },
    },
    sender: evmAddress(walletClient!.account.address),
    chainId: position.market.chain.chainId,
  });

  // …
};
```

```tsx title="Withdraw Native to Another Recipient"
import { useWalletClient } from "wagmi";
import { useWithdraw, bigDecimal, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [withdraw, withdrawing] = useWithdraw();

const execute = async () => {
  const result = await withdraw({
    market: position.market.address,
    amount: {
      native: {
        value: { exact: bigDecimal(2) }, // 2 ETH
      },
    },
    recipient: evmAddress("0x1234567890123456789012345678901234567890"),
    sender: evmAddress(walletClient!.account.address),
    chainId: position.market.chain.chainId,
  });

  // …
};
```

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

```ts title="Withdraw Exact Native Amount"
import { withdraw } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

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

const result = await withdraw(client, {
  market: position.market.address,
  amount: {
    native: {
      value: { exact: bigDecimal(2) }, // 2 ETH
    },
  },
  sender: evmAddress(wallet.account.address),
  chainId: position.market.chain.chainId,
});

// …
```

```ts title="Withdraw Max Native Amount"
import { withdraw } from "@aave/client/actions";
import { evmAddress } from "@aave/client";

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

const result = await withdraw(client, {
  market: position.market.address,
  amount: {
    native: {
      value: { max: true },
    },
  },
  sender: evmAddress(wallet.account.address),
  chainId: position.market.chain.chainId,
});

// …
```

</tab>
</tabgroup>
### 3. Process the Withdraw Execution Plan

Finally, handle the execution plan.

- **React**: Use the `useSendTransaction` hook for the [wallet library of your choice](../getting-started/react#send-aave-transactions) to send the transactions in the execution plan.
- **TypeScript**: Use `sendWith` for your [chosen wallet library](../getting-started/typescript#send-aave-transactions) to send the transactions in the execution plan, and await indexing with `client.waitForTransaction`.
- **GraphQL**: If the response is a `TransactionRequest`, you can send it directly using the wallet associated with the from address.

<tabgroup>
<tab label="React">

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

// …

const { data: walletClient } = useWalletClient();

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

// …

// Optional: combine loading states
const loading = withdrawing.loading || sending.loading;
const error = withdrawing.error || sending.error;

// …

const execute = async () => {
  const result = await withdraw({
    // …
  }).andThen((plan) => {
    switch (plan.__typename) {
      case "TransactionRequest":
        // Single transaction execution
        return sendTransaction(plan);

      case "ApprovalRequired":
        // Approval + transaction sequence
        return sendTransaction(plan.approval).andThen(() =>
          sendTransaction(plan.originalTransaction)
        );

      case "InsufficientBalanceError":
        return errAsync(
          new Error(`Insufficient balance: ${plan.required.value} required.`)
        );
    }
  });

  if (result.isErr()) {
    console.error("Withdraw failed:", result.error);
  } else {
    console.log("Withdraw successful with hash:", result.value);
  }
};
```

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

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

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

const result = await withdraw(client, {
  // …
})
  .andThen(sendWith(wallet))
  .andThen(client.waitForTransaction);

if (result.isErr()) {
  console.error("Withdraw failed:", result.error);
} else {
  console.log("Withdraw successful:", result.value);
}
```

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

```json title="TransactionRequest"
{
  "data": {
    "withdraw": {
      "__typename": "TransactionRequest",
      "to": "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2",
      "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
      "data": "0x69328dec000000000000000000000000c02…",
      "value": "0",
      "chainId": 1,
      "operation": "WITHDRAW"
    }
  }
}
```

</tab>
</tabgroup>
In GraphQL, if the response is an `ApprovalRequired`, you must first send the `approval` transaction. Once it succeeds, you can then send the `originalTransaction`.

```json title="ApprovalRequired"
{
  "data": {
    "withdraw": {
      "__typename": "ApprovalRequired",
      "reason": "Insufficient allowance for aToken transfer",
      "requiredAmount": {
        "value": "2.0",
        "decimals": 18
      },
      "currentAllowance": {
        "value": "0.0",
        "decimals": 18
      },
      "approval": {
        "to": "0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8",
        "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
        "data": "0x095ea7b3000000000000000000000000878…",
        "value": "0",
        "chainId": 1,
        "operation": null
      },
      "originalTransaction": {
        "to": "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2",
        "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
        "data": "0x69328dec000000000000000000000000c02…",
        "value": "0",
        "chainId": 1,
        "operation": "WITHDRAW"
      }
    }
  }
}
```

In GraphQL, if the response is an `InsufficientBalanceError`, inform the user that they don’t have enough balance to withdraw the requested amount.

```json title="InsufficientBalanceError"
{
  "data": {
    "withdraw": {
      "__typename": "InsufficientBalanceError",
      "required": {
        "value": "2.0",
        "decimals": 18
      },
      "available": {
        "value": "1.5",
        "decimals": 18
      }
    }
  }
}
```
