From f91b24ecdeaae8f761a5f64f2c72177240a59de3 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Sun, 16 Jan 2022 20:56:18 -0600 Subject: [PATCH 1/9] docs: update guide for fetching and formatting data --- README.md | 769 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 751 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 1cd4a2c8..73a1d3df 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,28 @@ -# Aave utilities +

Aave logo

-

- Aave logo

+

Aave Utilities

-

Aave utilities

+Aave is a decentralized non-custodial liquidity market protocol where users can +participate as depositors or borrowers. The Aave Protocol is a set of open +source smart contracts which facilitate the supply and borrowing of user funds. +These contracts, and all user transactions/balances are stored on a public +ledger called a blockchain, making them accessible to anyone + +This Aave utilities packages give developers access to methods for formatting +contract data and executing transactions on the Aave protocol, and is compatible +with both Aave V2 and V3 + +Aave Utilities is an upgrade to the existing +[aave-js](https://github.com/aave/aave-js) library, designed to be more modular, +efficient, and easier to use + +
## Installation -Aave utilities are available as npm -packages[¹](https://www.npmjs.com/package/@aave/contract-helpers)[²](https://www.npmjs.com/package/@aave/math-utils). +Aave utilities are available as npm packages, +[contract helpers](https://www.npmjs.com/package/@aave/contract-helpers), and +[math utils](https://www.npmjs.com/package/@aave/math-utils) ```sh // with npm @@ -17,24 +31,743 @@ npm install @aave/contract-helpers @aave/math-utils yarn add @aave/contract-helpers @aave/math-utils ``` -## Usage +
-Here is a quick example to get you started: +## Features + +1. [Data Formatting Methods](#data-formatting-methods) + - a. [Fetching Protocol Data](#fetching-protocol-data) + - [Smart Contract Calls](#smart-contract-calls) + - [Subgraph](#subgraph) + - [Caching Server](#caching-server) + - b. [Format Reserve Data](#reserve-data) + - [formatReserves](#formatReserves) + - [formatReservesAndIncentives](#formatReservesAndIncentives) + - c. [Format User Data](#user-data) + - [formatUserSummary](#formatUserSummary) + - [formatUserSummaryAndIncentives](#formatUserSummaryAndIncentives) +2. [Transaction Methods](#transaction-methods) + - a. [Provider Setup](#provider-setup) + - b. [Pool V3](#pool-v3) + - [supply](#supply) + - [signERC20Approval](#signERC20Approval) + - [supplyWithPermit](#supply-with-permit) + - [borrow](#borrow-v3) + - [repay](#repay-v3) + - [repayWithATokens](#repayWithATokens) + - [withdraw](#withdraw-v3) + - [swapBorrowRateMode](#swapBorrowRateMode-v3) + - [setUsageAsCollateral](#setUsageAsCollateral-v3) + - [liquidationCall](#liquidationCall-v3) + - [swapCollateral](#swapCollateral-v3) + - [repayWithCollateral](#repayWithCollateral-v3) + - [setUserEMode](#setUserEMode) + - c. [Lending Pool V2](#lending-pool-v2) + - [deposit](#deposit) + - [borrow](#borrow) + - [repay](#repay) + - [withdraw](#withdraw) + - [swapBorrowRateMode](#swapBorrowRateMode) + - [setUsageAsCollateral](#setUsageAsCollateral) + - [liquidationCall](#liquidationCall) + - [swapCollateral](#swapCollateral) + - [repayWithCollateral](#repayWithCollateral) + - d. [Flashloans](#flashloans) + - [V2](#flashloans-v2) + - [V3](#flashloans-v3) + - e. [Staking](#staking) + - [stake](#stake) + - [redeem](#redeem) + - [cooldown](#cooldown) + - [claimRewards](#claimRewards) + - f. [Governance V2](#governancev2) + - [Governance](#governance) + - [create](#create) + - [cancel](#cancel) + - [queue](#queue) + - [execute](#execute) + - [submitVote](#submitVote) + - [GovernanceDelegation](#governanceDelegation) + - [delegate](#delegate) + - [delegateByType](#delegateByType) + - g. [Faucets](#faucets) + - [mint](#mint) + +
+ +# Data Formatting Methods + +Users interact with the Aave protocol through a set of smart contracts. The +`@aave/math-utils` package is a collection of methods to take raw input data +from these contracts, and format to use on a frontend interface such as +[Aave UI](https://github.com/aave/aave-ui) or +[Aave info](https://github.com/sakulstra/info.aave) + +## Fetching Protocol Data + +Input data for these methods can be obtained in a variety of ways with some +samples below: + +- [Contract Queries](#contract-queries) +- [Subgraph](#subgraph) +- [Caching Server](#caching-server) + +
+ +### Contract Queries + +There are a variety of libraries which can be used to query the Aave protocol +smart contract. The basic process is: you provide the library with an rpc URL +and TypeChain bindings which will generate a typed sdk for interacting with +contract data + +The rpc endpoint is network-specific url will execute your requests to the +blockchain. The +[Aave UI networks config](https://github.com/aave/aave-ui/blob/master/src/ui-config/networks.ts) +gives a `publicJsonRPCUrl` for each supported network which can be used to make +requests **with** or **without** an API key. + +The following code snippets can be used to fetch data which can be passed +directly into [data formatting methods](#data-formatting-methods): + +- [ethers.js](#ethers.js) +- [web3.js](#web.js) +- [truffle](#truffle) + +
+ +### ethers.js + +[ethers.js](https://docs.ethers.io/v5/) is a library for interacting with +Ethereum and other EVM compatible blockchains. To install: + +```sh +npm install --save ethers +``` + +The first step to query contract data with ethers is to inialize a `provider`, +there are a [variety](https://docs.ethers.io/v5/api/providers/) to choose from, +all of them requiring the an rpcURL + +The sample code below includes an example of initializing a provider, and using +it query the helper contract data which can be passed directly into data +formatting methods. + +
+ Sample Code + +```ts +import { ethers } from 'ethers'; +import { + UiPoolDataProvider, + UiIncentiveDataProvider, + ChainId, +} from '@aave/contract-helpers'; + +// Sample RPC address for querying ETH mainnet +const provider = new ethers.provider.DefaultProvider( + 'https://cloudflare-eth.com', +); + +// This is the provider used in Aave UI, it checks the chainId locally to reduce RPC calls with frequent network switches, but requires that the rpc url and chainId to remain consistent with the request being sent from the wallet (i.e. - detecting the active chainId) +const providerAlt = new ethers.providers.StaticJsonRpcProvider( + 'https://cloudflare-eth.com', + ChainId.mainnet, +); + +// Aave protocol contract addresses, will be different for each market and can be found at https://docs.aave.com/developers/deployed-contracts/deployed-contracts or https://github.com/aave/aave-ui/blob/master/src/ui-config/markets/index.ts +const uiPoolDataProviderAddress = ''; +const uiIncentiveDataProviderAddress = ''; +const lendingPoolAddressProvider = ''; + +// User address to fetch data for +const currentAccount = ''; + +// View contract used to fetch all reserves data (including market base currency data), and user reserves +const poolDataProviderContract = new UiPoolDataProvider({ + uiPoolDataProviderAddress, + provider, +}); + +// View contract used to fetch all reserve incentives (APRs), and user incentives +const incentiveDataProviderContract = new UiIncentiveDataProvider({ + uiIncentiveDataProviderAddress, + provider, +}); + +// Object containing array of pool reserves and market base currency data +// { reservesArray, baseCurrencyData } +const reserves = await poolDataProviderContract.getReservesHumanized({ + lendingPoolAddressProvider, +}); + +// Object containing array or users aave positions and active eMode category +// { userReserves, userEmodeCategoryId } +const userReserves = await poolDataProviderContract.getUserReservesHumanized({ + lendingPoolAddressProvider, + currentAccount, +}); + +// Array of incentive tokens with price feed and emission APR +const reserveIncentives = + await incentiveDataProviderContract.getReservesIncentivesDataHumanized({ + lendingPoolAddressProvider, + }); + +// Dictionary of claimable user incentives +const userIncentives = + await incentiveDataProviderContract.getUserReservesIncentivesDataHumanized({ + lendingPoolAddressProvider, + currentAccount, + }); +``` + +
+ +
+ +### web.js + +
+ +### truffle + +
+ +### Subgraph + +A subgraph indexes events emitted from a smart contract and exposes a graphql +endpoing to query data from. Each network where the protocol is deployed is a +corresponding subgraph. Subgraph can be queried directly using the playground +(links below) and integrated into applications directly via TheGraph API. Check +out these guides from +[Aave](https://docs.aave.com/developers/getting-started/using-graphql) and +[TheGraph](https://thegraph.com/docs/en/developer/querying-from-your-app/) for +resources on querying subgraph from a frontend application. + +Here are queries for fetching the data fields required for +[data formatting methods](#data-formatting-methods). The formatting methods are +the same for V2 and V3, but the queries required to fetch the input data are +different. The result will need to be formatted + +
+ V2 + +```ts + +``` + +
+ +
+ V3 + +```ts + +``` + +
+ +
+ +### Caching Server + +Given that the Aave Ui has decentralized hosting with IPFS, it makes sense to +not require any API keys to run the UI, but this means only public rpc endpoints +are used which are quickly rate limited. To account for this, Aave has publushed +a [caching server](https://github.com/aave/aave-ui-caching-server) to perform +contract queries on one server, then serve this data to all frontend users +through a graphQL endpoint. + +The four queries to fetch input data (in both query and subscription form) are +located +[here](https://github.com/aave/aave-ui/tree/master/src/libs/caching-server-data-provider/graphql) +in the follow files: + +- protocol-data.graphql +- user-data.graphql +- incentives-data.graphql +- user-incentives-data.graphql + +Examples of hooks for fetching data with these queries are located +[here](https://github.com/aave/aave-ui/tree/master/src/libs/caching-server-data-provider/hooks). + +
+ +## Reserve Data + +Formatted reserve data is an array of tokens in the Aave market, including +supply, borrow rates, configuration, + +### formatReserves + +Description + +
+ Parameters + +```ts +- @param `reserves` - Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` +- @param `currentTimestamp` - Current UNIX timestamp in seconds +- @param `marketReferencePriceInUsd` - Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` - Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +``` + +
+ +
+ Sample Code + +```ts +import { formatReserves } from '@aave/math-utils'; + +// reserves input from Fetching Protocol Data section + +const reservesArray = reserves.reservesData; +const baseCurrencyData = reserves.baseCurrencyData; + +const currentTimestamp = Math.round(new Date().getTime() / 1000); + +const formattedPoolReserves = formatReserves({ + reserves: reservesArray, + currentTimestamp, + marketReferenceCurrencyDecimals: + baseCurrencyData.marketReferenceCurrencyDecimals, + marketReferencePriceInUsd: baseCurrencyData.marketReferenceCurrencyPriceInUsd, +}); +``` + +
+ +
+ +### formatReservesAndIncentives + +
+ Parameters + +```ts +- @param `reserves` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` +- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `reserveIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` +``` + +
+ +
+ Sample Code + +```ts +import { formatReservesAndIncentives } from '@aave/math-utils'; + +// 'reserves' and 'reserveIncentives' inputs from Fetching Protocol Data section + +const reservesArray = reserves.reservesData; +const baseCurrencyData = reserves.baseCurrencyData; + +const currentTimestamp = Math.round(new Date().getTime() / 1000); + +const formattedPoolReserves = formatReservesAndIncentives({ + reserves: reservesArray, + currentTimestamp, + marketReferenceCurrencyDecimals: + baseCurrencyData.marketReferenceCurrencyDecimals, + marketReferencePriceInUsd: baseCurrencyData.marketReferenceCurrencyPriceInUsd, + reserveIncentives, +}); +``` + +
+ +
+ +## User Data + +Description + +### formatUserSummary + +Returns formatted summary of Aave user portfolio including: array of holdings, +total liquidity, total collateral, total borrows, liquidation threshold, health +factor, and available borrowing power. + +
+ Parameters + +```ts +- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `userReserves` Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` +- @param `userEmodeCategoryId` Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` +``` + +
+ +
+ Sample Code + +```ts +import { formatUserSummary } from '@aave/math-utils'; + +// 'reserves' and 'userReserves' inputs from Fetching Protocol Data section + +const reservesArray = reserves.reservesData; +const baseCurrencyData = reserves.baseCurrencyData; +const userReservesArray = userReserves.userReserves; + +const currentTimestamp = Math.round(new Date().getTime() / 1000); + +// Combine reserve data with user data +const userReservesFormatted: UserReserveData[] = []; +if (userReservesArray && reservesArray.length) { + userReservesArray.forEach(rawUserReserve => { + const reserve = reservesArray.find( + r => + r.underlyingAsset.toLowerCase() === + rawUserReserve.underlyingAsset.toLowerCase(), + ); + if (reserve) { + userReservesFormatted.push({ + ...rawUserReserve, + reserve, + }); + } + }); +} + +const userSummary = formatUserSummaryAndIncentives({ + currentTimestamp, + marketReferencePriceInUsd: baseCurrencyData.marketReferenceCurrencyPriceInUsd, + marketReferenceCurrencyDecimals: + baseCurrencyData.marketReferenceCurrencyDecimals, + userReserves: userReservesFormatted, + userEmodeCategoryId: userReserves.userEmodeCategoryId, +}); +``` + +
+ +
+ +### formatUserSummaryAndIncentives + +Returns formatted summary of Aave user portfolio including: array of holdings, +total liquidity, total collateral, total borrows, liquidation threshold, health +factor, available borrowing power, and dictionary of claimable incentives + +
+ Parameters + +```ts +- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `userReserves` Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` +- @param `userEmodeCategoryId` Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` +- @param `reserveIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` +- @param `userIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `userIncentives` +``` + +
+ +
+ Sample Code ```ts -import { PermissionManager } from '@aave/contract-helpers'; +// 'reserves', 'userReserves', 'reserveIncentives', and 'userIncentives' inputs from Fetching Protocol Data section -const instance = new PermissionManager({ - provider: rpcProvider, - permissionManagerAddress: permissionManagerAddress, +const reservesArray = reserves.reservesData; +const baseCurrencyData = reserves.baseCurrencyData; +const userReservesArray = userReserves.userReserves; + +const currentTimestamp = Math.round(new Date().getTime() / 1000); + +// Combine reserve data with user data +const userReservesFormatted: UserReserveData[] = []; +if (userReservesArray && reservesArray.length) { + userReservesArray.forEach(rawUserReserve => { + const reserve = reservesArray.find( + r => + r.underlyingAsset.toLowerCase() === + rawUserReserve.underlyingAsset.toLowerCase(), + ); + if (reserve) { + userReservesFormatted.push({ + ...rawUserReserve, + reserve, + }); + } + }); +} + +const userSummary = formatUserSummaryAndIncentives({ + currentTimestamp, + marketReferencePriceInUsd: baseCurrencyData.marketReferenceCurrencyPriceInUsd, + marketReferenceCurrencyDecimals: + baseCurrencyData.marketReferenceCurrencyDecimals, + userReserves: userReservesFormatted, + userEmodeCategoryId: userReserves.userEmodeCategoryId, + reserveIncentives, + userIncentives, }); -const permissions = await instance.getHumanizedUserPermissions(walletAddress); ``` -## Examples +
+ +
+ +# Transaction Methods + +## Markets and Networks + +The library exports the enabled networks and markets in the Aave protocol as the +enums `Network` and `Market` + +```ts +import { Network, Market } from '@aave/contract-helpers'; +``` + +## Usage + +```ts +import { TxBuilderV2, Network, Market } from '@aave/protocol-js'; + +const httpProvider = new Web3.providers.HttpProvider( + process.env.ETHEREUM_URL || 'https://kovan.infura.io/v3/', +); +const txBuilder = new TxBuilderV2(Network.main, httpProvider); + +lendingPool = txBuilder.getLendingPool(Market.main); // get all lending pool methods +``` + +## Providers + +The library accepts 3 kinds of providers: + +- web3 provider +- JsonRPC url +- no provider: if no provider is passed it will default to ethers Infura / + etherscan providers (shared providers, do not use in production) + +To learn more about supported providers, see the +[ethers documentation on providers](https://docs.ethers.io/v5/api/providers/#providers). + +## Lending Pool V2 + +Object that contains all the necessary methods to create Aave lending pool +transactions. + +The return object will be a Promise array of objects of type: + +`ts import { EthereumTransactionTypeExtended } from '@aave/protocol-js' ` + +having {tx, txType} + +- tx: object with transaction fields. - txType: string determining the kinds of + transaction. + +### deposit + +Deposits the underlying asset into the reserve. A corresponding amount of the +overlying asset (aTokens) is minted. + +- @param `user` The ethereum address that will make the deposit - @param + `reserve` The ethereum address of the reserve - @param `amount` The amount to + be deposited - @param @optional `onBehalfOf` The ethereum address for which + user is depositing. It will default to the user address - @param @optional + `referralCode` Integrators are assigned a referral code and can potentially + receive rewards. It defaults to 0 (no referrer) + +`ts lendingPool.deposit({ user, // string, reserve, // string, amount, // string, onBehalfOf, // ? string, referralCode, // ? string, }); ` + +If the `user` is not approved, an approval transaction will also be returned. + +### borrow + +Borrow an `amount` of `reserve` asset. + +User must have a collaterised position (i.e. aTokens in their wallet) + +- @param `user` The ethereum address that will receive the borrowed amount - + @param `reserve` The ethereum address of the reserve asset - @param `amount` + The amount to be borrowed, in human readable units (e.g. 2.5 ETH) - @param + `interestRateMode` Whether the borrow will incur a stable or variable interest + rate (1 | 2) - @param @optional `debtTokenAddress` The ethereum address of the + debt token of the asset you want to borrow. Only needed if the reserve is ETH + mock address - @param @optional `onBehalfOf` The ethereum address for which + user is borrowing. It will default to the user address - @param @optional + `refferalCode` Integrators are assigned a referral code and can potentially + receive rewards. It defaults to 0 (no referrer) + +````ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } + +lendingPool.borrow({ user, // string, reserve, // string, amount, // string, interestRateMode, // InterestRate; debtTokenAddress, // ? string; onBehalfOf, // ? string; referralCode, // ? string; }); ``` + +### repay + +Repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if (-1) is specified). the target user is defined by `onBehalfOf`. If there is no repayment on behalf of another account, `onBehalfOf` must be equal to `user`. + +- @param `user` The ethereum address that repays - @param `reserve` The ethereum address of the reserve on which the user borrowed - @param `amount` The amount to repay, or (-1) if the user wants to repay everything - @param `interestRateMode` Whether the borrow will incur a stable or variable interest rate (1 | 2) - @param @optional `onBehalfOf` The ethereum address for which user is repaying. It will default to the user address + +```ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } + +lendingPool.repay({ user, // string, reserve, // string, amount, // string, interestRateMode, // InterestRate; onBehalfOf, // ? string }); ``` + +If the `user` is not approved, an approval transaction will also be returned. + +### withdraw + +Withdraws the underlying asset of an aToken asset. + +- @param `user` The ethereum address that will receive the aTokens - @param `reserve` The ethereum address of the reserve asset - @param `amount` The amount of aToken being redeemed - @param @optional `aTokenAddress` The ethereum address of the aToken. Only needed if the reserve is ETH mock address - @param @optional `onBehalfOf` The amount of aToken being redeemed. It will default to the user address + +```ts lendingPool.withdraw({ user, // string, reserve, // string, amount, // string, aTokenAddress, // ? string, onBehalfOf, // ? string }); ``` + +### swapBorrowRateMode + +Borrowers can use this function to swap between stable and variable borrow rate modes. + +- @param `user` The ethereum address that wants to swap rate modes - @param `reserve` The address of the reserve on which the user borrowed - @param `interestRateMode` Whether the borrow will incur a stable or variable interest rate (1 | 2) + +```ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } + +lendingPool.swapBorrowRateMode({ user, // string, reserve, // string, interestRateMode, // InterestRate; }); ``` + +### setUsageAsCollateral + +Allows depositors to enable or disable a specific deposit as collateral. + +- @param `user` The ethereum address that enables or disables the deposit as collateral - @param `reserve` The ethereum address of the reserve - @param `useAsCollateral` True if the user wants to use the deposit as collateral, false otherwise. + +```ts lendingPool.setUsageAsCollateral({ user, // string, reserve, // string, usageAsCollateral, // boolean }); ``` + +### liquidationCall + +Users can invoke this function to liquidate an undercollateralized position. + +- @param `liquidator` The ethereum address that will liquidate the position - @param `liquidatedUser` The address of the borrower - @param `debtReserve` The ethereum address of the principal reserve - @param `collateralReserve` The address of the collateral to liquidated - @param `purchaseAmount` The amount of principal that the liquidator wants to repay - @param @optional `getAToken` Boolean to indicate if the user wants to receive the aToken instead of the asset. Defaults to false + +```ts lendingPool.liquidationCall({ liquidator, // string; liquidatedUser, // string; debtReserve, // string; collateralReserve, // string; purchaseAmount, // string; getAToken, // ? boolean; }); ``` + +### swapCollateral + +Allows users to swap a collateral to another asset + +- @param `user` The ethereum address that will liquidate the position - @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false - @param `fromAsset` The ethereum address of the asset you want to swap - @param `fromAToken` The ethereum address of the aToken of the asset you want to swap - @param `toAsset` The ethereum address of the asset you want to swap to (get) - @param `fromAmount` The amount you want to swap - @param `toAmount` The amount you want to get after the swap - @param `maxSlippage` The max slippage that the user accepts in the swap - @param @optional `permitSignature` A permit signature of the tx. Only needed when previously signed (Not needed at the moment). - @param `swapAll` Bool indicating if the user wants to swap all the current collateral - @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address - @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) - @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false + +```ts type PermitSignature = { amount: tStringCurrencyUnits; deadline: string; v: number; r: BytesLike; s: BytesLike; }; + +await lendingPool.swapCollateral({ user, // string; flash, // ? boolean; fromAsset, // string; fromAToken, // string; toAsset, // string; fromAmount, // string; toAmount, // string; maxSlippage, // string; permitSignature, // ? PermitSignature; swapAll, // boolean; onBehalfOf, // ? string; referralCode, // ? string; useEthPath, // ? boolean; }); ``` + +### repayWithCollateral + +Allows a borrower to repay the open debt with the borrower collateral + +- @param `user` The ethereum address that will liquidate the position - @param `fromAsset` The ethereum address of the asset you want to repay with (collateral) - @param `fromAToken` The ethereum address of the aToken of the asset you want to repay with (collateral) - @param `assetToRepay` The ethereum address of the asset you want to repay - @param `repayWithAmount` The amount of collateral you want to repay the debt with - @param `repayAmount` The amount of debt you want to repay - @param `permitSignature` A permit signature of the tx. Optional - @param @optional `repayAllDebt` Bool indicating if the user wants to repay all current debt. Defaults to false - @param `rateMode` Enum indicating the type of the interest rate of the collateral - @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address - @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) - @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false - @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false + +```ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } + +await lendingPool.repayWithCollateral({ user, // string; fromAsset, // string; fromAToken, // string; assetToRepay, // string repayWithAmount, // string; repayAmount, // string; permitSignature, // ? PermitSignature; repayAllDebt, // ? boolean; rateMode, // InterestRate; onBehalfOf, // ? string; referralCode, // ? string; flash, // ? boolean; useEthPath, // ? boolean; }); ``` + +## Flashloans + +### V2 Flashloans +### V3 Flashloans + +## Governance V2 + +Example of how to use the governance service + +```ts import { TxBuilderV2, AaveGovernanceV2Interface, GovernanceDelegationTokenInterface, } from '@aave/protocol-js'; + +const httpProvider = new Web3.providers.HttpProvider( process.env.ETHEREUM_URL || "https://kovan.infura.io/v3/" ); const txBuilder = new TxBuilderV2(Network.main, httpProvider); const gov2 = txBuilder.aaveGovernanceV2Service; const powerDelegation = txBuilder.governanceDelegationTokenService; ``` + +### create + +Creates a Proposal (needs to be validated by the Proposal Validator) + +- @param `user` The ethereum address that will create the proposal - @param `targets` list of contracts called by proposal's associated transactions - @param `values` list of value in wei for each propoposal's associated transaction - @param `signatures` list of function signatures (can be empty) to be used when created the callData - @param `calldatas` list of calldatas: if associated signature empty, calldata ready, else calldata is arguments - @param `withDelegatecalls` boolean, true = transaction delegatecalls the taget, else calls the target - @param `ipfsHash` IPFS hash of the proposal - @param `executor` The ExecutorWithTimelock contract that will execute the proposal + +```ts enum ExecutorType { Short, Long, } + +-------- + +gov2.create({ user. // string; targets, //string[]; values, // string[]; signatures, // string[]; calldatas, // BytesLike[]; withDelegateCalls, // boolean[]; ipfsHash, // BytesLike; executor, // ExecutorType; }); ``` + +### cancel + +Cancels a Proposal. Callable by the \_guardian with relaxed conditions, or by anybody if the conditions of cancellation on the executor are fulfilled + +- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to cancel + +```ts gov2.cancel({ user, // string proposalId, // number }) ``` + +### queue + +Queue the proposal (If Proposal Succeeded) + +- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to queue + +```ts gov2.queue({ user, // string proposalId, // number }) ``` + +### execute + +Execute the proposal (If Proposal Queued) + +- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to execute + +```ts gov2.execute({ user, // string proposalId, // number }) ``` + +### submitVote + +Function allowing msg.sender to vote for/against a proposal + +- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to vote - @param `support` Bool indicating if you are voting in favor (true) or against (false) + +```ts gov2.submitVote({ user, // string proposalId, // number support, // boolean }) ``` + +## Governance Delegation + +### delegate + +Method for the user to delegate voting `and` proposition power to the chosen address + +- @param `user` The ethereum address that will create the proposal - @param `delegatee` The ethereum address to which the user wants to delegate proposition power and voting power - @param `governanceToken` The ethereum address of the governance token + +```ts powerDelegation.delegate({ user, // string delegatee, // string governanceToken // string }); ``` + +### delegateByType + +Method for the user to delegate voting `or` proposition power to the chosen address + +- @param `user` The ethereum address that will create the proposal - @param `delegatee` The ethereum address to which the user wants to delegate proposition power and voting power - @param `delegationType` The type of the delegation the user wants to do: voting power ('0') or proposition power ('1') - @param `governanceToken` The ethereum address of the governance token + +```ts powerDelegation.delegateByType({ user, // string delegatee, // string delegationType, // string governanceToken // string }); ``` + +## Faucets + +To use the testnet faucets which are compatible with Aave: + +```ts import { TxBuilderV2, Network, Market } from '@aave/protocol-js' + +const httpProvider = new Web3.providers.HttpProvider( process.env.ETHEREUM_URL || "https://kovan.infura.io/v3/" ); const txBuilder = new TxBuilderV2(Network.main, httpProvider); const faucet = txBuilder.faucetService; ``` + +### mint + +Mint tokens for the usage on the Aave protocol on the Kovan network. The amount of minted tokens is fixed and depends on the token + +- @param `userAddress` The ethereum address of the wallet the minted tokens will go - @param `reserve` The ethereum address of the token you want to mint - @param `tokenSymbol` The symbol of the token you want to mint + +```ts faucet.mint({ userAddress, // string reserve, // string tokenSymbol, // string }); ``` + +## Usage + +Here is a quick example to get you started: -Are you looking for an example project to get started? Check out repositories -relying on this library: +```ts import { PermissionManager } from '@aave/contract-helpers'; -- [The open source aave ui](https://github.com/aave/aave-ui) -- [Aave info](https://github.com/sakulstra/info.aave) +const instance = new PermissionManager({ provider: rpcProvider, permissionManagerAddress: permissionManagerAddress, }); const permissions = await instance.getHumanizedUserPermissions(walletAddress); ``` +```` From f28a261bc1c9814ff5d161bbd8aa114e0506cce7 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Mon, 17 Jan 2022 00:51:28 -0600 Subject: [PATCH 2/9] feat: update V2 transaction method docs --- README.md | 592 ++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 444 insertions(+), 148 deletions(-) diff --git a/README.md b/README.md index 73a1d3df..82d67c89 100644 --- a/README.md +++ b/README.md @@ -307,10 +307,10 @@ Description Parameters ```ts -- @param `reserves` - Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` -- @param `currentTimestamp` - Current UNIX timestamp in seconds -- @param `marketReferencePriceInUsd` - Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` - Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `reserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` +- @param `currentTimestamp` //Current UNIX timestamp in seconds +- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` ``` @@ -347,11 +347,11 @@ const formattedPoolReserves = formatReserves({ Parameters ```ts -- @param `reserves` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` -- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) -- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` -- @param `reserveIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` +- @param `reserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` +- @param `currentTimestamp` //Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `reserveIncentives` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` ``` @@ -397,11 +397,11 @@ factor, and available borrowing power. Parameters ```ts -- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) -- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` -- @param `userReserves` Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` -- @param `userEmodeCategoryId` Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` +- @param `currentTimestamp` //Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `userReserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` +- @param `userEmodeCategoryId` //Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` ``` @@ -462,13 +462,13 @@ factor, available borrowing power, and dictionary of claimable incentives Parameters ```ts -- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) -- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` -- @param `userReserves` Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` -- @param `userEmodeCategoryId` Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` -- @param `reserveIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` -- @param `userIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `userIncentives` +- @param `currentTimestamp` //Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `userReserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` +- @param `userEmodeCategoryId` //Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` +- @param `reserveIncentives` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` +- @param `userIncentives` //Input from [Fetching Protocol Data](#fetching-protocol-data), `userIncentives` ``` @@ -521,69 +521,76 @@ const userSummary = formatUserSummaryAndIncentives({ # Transaction Methods -## Markets and Networks +The transaction methods package provides an sdk to interact with Aave Protocol +contracts. See [ethers.js](#ethers.js) for instructions on installing setting up +and ethers provider -The library exports the enabled networks and markets in the Aave protocol as the -enums `Network` and `Market` +Once initialized this sdk can be used to generate the transaction data needed to +perform an action. If an approval is required, the method will return an array +with two transactions, or single transaction if no approval is needed + +Transactions objects will be of this type: ```ts -import { Network, Market } from '@aave/contract-helpers'; +import { EthereumTransactionTypeExtended } from '@aave/contract-helpers'; ``` -## Usage +To send a transaction from this object: ```ts -import { TxBuilderV2, Network, Market } from '@aave/protocol-js'; +import { BigNumber } from 'ethers'; -const httpProvider = new Web3.providers.HttpProvider( - process.env.ETHEREUM_URL || 'https://kovan.infura.io/v3/', -); -const txBuilder = new TxBuilderV2(Network.main, httpProvider); +// initialize provider +// tx of type EthereumTransactionTypeExtended -lendingPool = txBuilder.getLendingPool(Market.main); // get all lending pool methods +const extendedTxData = await tx.unsignedData(); +const { from, ...txData } = extendedTxData; +const signer = provider.getSigner(from); +const txResponse = await signer.sendTransaction({ + ...txData, + value: txData.value ? BigNumber.from(txData.value) : undefined, +}); ``` -## Providers - -The library accepts 3 kinds of providers: - -- web3 provider -- JsonRPC url -- no provider: if no provider is passed it will default to ethers Infura / - etherscan providers (shared providers, do not use in production) - -To learn more about supported providers, see the -[ethers documentation on providers](https://docs.ethers.io/v5/api/providers/#providers). +## Pool V3 ## Lending Pool V2 -Object that contains all the necessary methods to create Aave lending pool -transactions. +Object that contains all the necessary methods to create Aave V2 lending pool +transactions -The return object will be a Promise array of objects of type: +### deposit -`ts import { EthereumTransactionTypeExtended } from '@aave/protocol-js' ` +Deposits the underlying asset into the reserve. For every token that is +deposited, a corresponding amount of aTokens is minted -having {tx, txType} +
+ Sample Code -- tx: object with transaction fields. - txType: string determining the kinds of - transaction. +```ts +import { LendingPool } from '@aave/contract-helpers'; -### deposit +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); -Deposits the underlying asset into the reserve. A corresponding amount of the -overlying asset (aTokens) is minted. +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `amount` The amount to be deposited +- @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address +*/ +const txs = await lendingPool.deposit({ user, reserve, amount, onBehalfOf }); -- @param `user` The ethereum address that will make the deposit - @param - `reserve` The ethereum address of the reserve - @param `amount` The amount to - be deposited - @param @optional `onBehalfOf` The ethereum address for which - user is depositing. It will default to the user address - @param @optional - `referralCode` Integrators are assigned a referral code and can potentially - receive rewards. It defaults to 0 (no referrer) +// Submit transaction(s) as shown in Transaction Methods header +``` -`ts lendingPool.deposit({ user, // string, reserve, // string, amount, // string, onBehalfOf, // ? string, referralCode, // ? string, }); ` +
-If the `user` is not approved, an approval transaction will also be returned. +
### borrow @@ -591,183 +598,472 @@ Borrow an `amount` of `reserve` asset. User must have a collaterised position (i.e. aTokens in their wallet) -- @param `user` The ethereum address that will receive the borrowed amount - - @param `reserve` The ethereum address of the reserve asset - @param `amount` - The amount to be borrowed, in human readable units (e.g. 2.5 ETH) - @param - `interestRateMode` Whether the borrow will incur a stable or variable interest - rate (1 | 2) - @param @optional `debtTokenAddress` The ethereum address of the - debt token of the asset you want to borrow. Only needed if the reserve is ETH - mock address - @param @optional `onBehalfOf` The ethereum address for which - user is borrowing. It will default to the user address - @param @optional - `refferalCode` Integrators are assigned a referral code and can potentially - receive rewards. It defaults to 0 (no referrer) + -````ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } +
+ Sample Code -lendingPool.borrow({ user, // string, reserve, // string, amount, // string, interestRateMode, // InterestRate; debtTokenAddress, // ? string; onBehalfOf, // ? string; referralCode, // ? string; }); ``` +```ts +import { LendingPool, InterestRate } from '@aave/contract-helpers'; + +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` //The ethereum address that will receive the borrowed amount +- @param `reserve` //The ethereum address of the reserve asset +- @param `amount` //The amount to be borrowed, in human readable units (e.g. 2.5 ETH) +- @param `interestRateMode`//Whether the borrow will incur a stable or variable interest rate (1 | 2) +- @param @optional `debtTokenAddress` //The ethereum address of the debt token of the asset you want to borrow. Only needed if the reserve is ETH mock address +- @param @optional `onBehalfOf` //The ethereum address for which user is borrowing. It will default to the user address +*/ +const txs = await lendingPool.borrow({ + user, + reserve, + amount, + interestRateMode, + debtTokenAddress, + onBehalfOf, + referralCode, +}); + +// Submit transaction(s) as shown in Transaction Methods header +``` + +
+ +
### repay -Repays a borrow on the specific reserve, for the specified amount (or for the whole amount, if (-1) is specified). the target user is defined by `onBehalfOf`. If there is no repayment on behalf of another account, `onBehalfOf` must be equal to `user`. +Repays a borrow on the specific reserve, for the specified amount (or for the +whole amount, if (-1) is specified). the target user is defined by `onBehalfOf`. +If there is no repayment on behalf of another account, `onBehalfOf` must be +equal to `user` -- @param `user` The ethereum address that repays - @param `reserve` The ethereum address of the reserve on which the user borrowed - @param `amount` The amount to repay, or (-1) if the user wants to repay everything - @param `interestRateMode` Whether the borrow will incur a stable or variable interest rate (1 | 2) - @param @optional `onBehalfOf` The ethereum address for which user is repaying. It will default to the user address +If the `user` is not approved, an approval transaction will also be returned -```ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } +
+ Sample Code -lendingPool.repay({ user, // string, reserve, // string, amount, // string, interestRateMode, // InterestRate; onBehalfOf, // ? string }); ``` +```ts +import { LendingPool, InterestRate } from '@aave/contract-helpers'; -If the `user` is not approved, an approval transaction will also be returned. +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` //The ethereum address that repays +- @param `reserve` //The ethereum address of the reserve on which the user borrowed +- @param `amount` //The amount to repay, or (-1) if the user wants to repay everything +- @param `interestRateMode` //Whether the borrow will incur a stable or variable interest rate (1 | 2) +- @param @optional `onBehalfOf` //The ethereum address for which user is repaying. It will default to the user address +*/ +const txs = lendingPool.repay({ + user, + reserve, + amount, + interestRateMode, + onBehalfOf, +}); + +// Submit transaction(s) as shown in Transaction Methods header +``` + +
+ +
### withdraw Withdraws the underlying asset of an aToken asset. -- @param `user` The ethereum address that will receive the aTokens - @param `reserve` The ethereum address of the reserve asset - @param `amount` The amount of aToken being redeemed - @param @optional `aTokenAddress` The ethereum address of the aToken. Only needed if the reserve is ETH mock address - @param @optional `onBehalfOf` The amount of aToken being redeemed. It will default to the user address +
+ Sample Code -```ts lendingPool.withdraw({ user, // string, reserve, // string, amount, // string, aTokenAddress, // ? string, onBehalfOf, // ? string }); ``` +```ts +import { LendingPool } from '@aave/contract-helpers'; -### swapBorrowRateMode +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); -Borrowers can use this function to swap between stable and variable borrow rate modes. +/* +- @param `user` //The ethereum address that will receive the aTokens +- @param `reserve` //The ethereum address of the reserve asset +- @param `amount` //The amount of aToken being redeemed +- @param @optional `aTokenAddress` //The ethereum address of the aToken. Only needed if the reserve is ETH mock address +- @param @optional `onBehalfOf` //The amount of aToken being redeemed. It will default to the user address +*/ +const txs = lendingPool.withdraw({ + user, + reserve, + amount, + aTokenAddress, + onBehalfOf, +}); -- @param `user` The ethereum address that wants to swap rate modes - @param `reserve` The address of the reserve on which the user borrowed - @param `interestRateMode` Whether the borrow will incur a stable or variable interest rate (1 | 2) +// Submit transaction(s) as shown in Transaction Methods header +``` -```ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } +
-lendingPool.swapBorrowRateMode({ user, // string, reserve, // string, interestRateMode, // InterestRate; }); ``` +
-### setUsageAsCollateral +### swapBorrowRateMode -Allows depositors to enable or disable a specific deposit as collateral. +Borrowers can use this function to swap between stable and variable borrow rate +modes. -- @param `user` The ethereum address that enables or disables the deposit as collateral - @param `reserve` The ethereum address of the reserve - @param `useAsCollateral` True if the user wants to use the deposit as collateral, false otherwise. +
+ Sample Code -```ts lendingPool.setUsageAsCollateral({ user, // string, reserve, // string, usageAsCollateral, // boolean }); ``` +```ts +import { LendingPool, InterestRate } from '@aave/contract-helpers'; -### liquidationCall +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); -Users can invoke this function to liquidate an undercollateralized position. +/* +- @param `user` //The ethereum address that wants to swap rate modes +- @param `reserve` //The address of the reserve on which the user borrowed +- @param `interestRateMode` //Whether the borrow will incur a stable or variable interest rate (1 | 2) +*/ +const txs = lendingPool.swapBorrowRateMode({ user, reserve, interestRateMode }); +// Submit transaction(s) as shown in Transaction Methods header +``` -- @param `liquidator` The ethereum address that will liquidate the position - @param `liquidatedUser` The address of the borrower - @param `debtReserve` The ethereum address of the principal reserve - @param `collateralReserve` The address of the collateral to liquidated - @param `purchaseAmount` The amount of principal that the liquidator wants to repay - @param @optional `getAToken` Boolean to indicate if the user wants to receive the aToken instead of the asset. Defaults to false +
-```ts lendingPool.liquidationCall({ liquidator, // string; liquidatedUser, // string; debtReserve, // string; collateralReserve, // string; purchaseAmount, // string; getAToken, // ? boolean; }); ``` +
-### swapCollateral +### setUsageAsCollateral -Allows users to swap a collateral to another asset +Allows depositors to enable or disable a specific deposit as collateral. -- @param `user` The ethereum address that will liquidate the position - @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false - @param `fromAsset` The ethereum address of the asset you want to swap - @param `fromAToken` The ethereum address of the aToken of the asset you want to swap - @param `toAsset` The ethereum address of the asset you want to swap to (get) - @param `fromAmount` The amount you want to swap - @param `toAmount` The amount you want to get after the swap - @param `maxSlippage` The max slippage that the user accepts in the swap - @param @optional `permitSignature` A permit signature of the tx. Only needed when previously signed (Not needed at the moment). - @param `swapAll` Bool indicating if the user wants to swap all the current collateral - @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address - @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) - @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false +
+ Sample Code -```ts type PermitSignature = { amount: tStringCurrencyUnits; deadline: string; v: number; r: BytesLike; s: BytesLike; }; +```ts +import { LendingPool, InterestRate } from '@aave/contract-helpers'; -await lendingPool.swapCollateral({ user, // string; flash, // ? boolean; fromAsset, // string; fromAToken, // string; toAsset, // string; fromAmount, // string; toAmount, // string; maxSlippage, // string; permitSignature, // ? PermitSignature; swapAll, // boolean; onBehalfOf, // ? string; referralCode, // ? string; useEthPath, // ? boolean; }); ``` +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); -### repayWithCollateral +/* +- @param `user` //The ethereum address that enables or disables the deposit as collateral +- @param `reserve` //The ethereum address of the reserve +- @param `useAsCollateral` //True if the user wants to use the deposit as collateral, false otherwise. +*/ +const txs = lendingPool.setUsageAsCollateral({ + user, + reserve, + usageAsCollateral, +}); +// Submit transaction(s) as shown in Transaction Methods header +``` -Allows a borrower to repay the open debt with the borrower collateral +
-- @param `user` The ethereum address that will liquidate the position - @param `fromAsset` The ethereum address of the asset you want to repay with (collateral) - @param `fromAToken` The ethereum address of the aToken of the asset you want to repay with (collateral) - @param `assetToRepay` The ethereum address of the asset you want to repay - @param `repayWithAmount` The amount of collateral you want to repay the debt with - @param `repayAmount` The amount of debt you want to repay - @param `permitSignature` A permit signature of the tx. Optional - @param @optional `repayAllDebt` Bool indicating if the user wants to repay all current debt. Defaults to false - @param `rateMode` Enum indicating the type of the interest rate of the collateral - @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address - @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) - @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false - @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false +
-```ts enum InterestRate { None = 'None', Stable = 'Stable', Variable = 'Variable', } +### liquidationCall -await lendingPool.repayWithCollateral({ user, // string; fromAsset, // string; fromAToken, // string; assetToRepay, // string repayWithAmount, // string; repayAmount, // string; permitSignature, // ? PermitSignature; repayAllDebt, // ? boolean; rateMode, // InterestRate; onBehalfOf, // ? string; referralCode, // ? string; flash, // ? boolean; useEthPath, // ? boolean; }); ``` +Users can invoke this function to liquidate an undercollateralized position. -## Flashloans + -### V2 Flashloans -### V3 Flashloans +
+ Sample Code -## Governance V2 +```ts +import { LendingPool } from '@aave/contract-helpers'; -Example of how to use the governance service +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); -```ts import { TxBuilderV2, AaveGovernanceV2Interface, GovernanceDelegationTokenInterface, } from '@aave/protocol-js'; +/* +- @param `liquidator` //The ethereum address that will liquidate the position +- @param `liquidatedUser` //The address of the borrower +- @param `debtReserve` //The ethereum address of the principal reserve +- @param `collateralReserve` //The address of the collateral to liquidated +- @param `purchaseAmount` //The amount of principal that the liquidator wants to repay +- @param @optional `getAToken` //Boolean to indicate if the user wants to receive the aToken instead of the asset. Defaults to false +*/ +const txs = lendingPool.liquidationCall({ + liquidator, + liquidatedUser, + debtReserve, + collateralReserve, + purchaseAmount, + getAToken, +}); +// Submit transaction(s) as shown in Transaction Methods header +``` -const httpProvider = new Web3.providers.HttpProvider( process.env.ETHEREUM_URL || "https://kovan.infura.io/v3/" ); const txBuilder = new TxBuilderV2(Network.main, httpProvider); const gov2 = txBuilder.aaveGovernanceV2Service; const powerDelegation = txBuilder.governanceDelegationTokenService; ``` +
-### create +
-Creates a Proposal (needs to be validated by the Proposal Validator) +### swapCollateral -- @param `user` The ethereum address that will create the proposal - @param `targets` list of contracts called by proposal's associated transactions - @param `values` list of value in wei for each propoposal's associated transaction - @param `signatures` list of function signatures (can be empty) to be used when created the callData - @param `calldatas` list of calldatas: if associated signature empty, calldata ready, else calldata is arguments - @param `withDelegatecalls` boolean, true = transaction delegatecalls the taget, else calls the target - @param `ipfsHash` IPFS hash of the proposal - @param `executor` The ExecutorWithTimelock contract that will execute the proposal +Allows users to swap a collateral to another asset -```ts enum ExecutorType { Short, Long, } +
+ Sample Code + +```ts +import { + LendingPool, + InterestRate, + PermitSignature, +} from '@aave/contract-helpers'; --------- +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); -gov2.create({ user. // string; targets, //string[]; values, // string[]; signatures, // string[]; calldatas, // BytesLike[]; withDelegateCalls, // boolean[]; ipfsHash, // BytesLike; executor, // ExecutorType; }); ``` +/* +- @param `user` //The ethereum address that will liquidate the position +- @param @optional `flash` //If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false +- @param `fromAsset` //The ethereum address of the asset you want to swap +- @param `fromAToken` //The ethereum address of the aToken of the asset you want to swap +- @param `toAsset` //The ethereum address of the asset you want to swap to (get) +- @param `fromAmount` //The amount you want to swap +- @param `toAmount` //The amount you want to get after the swap +- @param `maxSlippage` //The max slippage that the user accepts in the swap +- @param @optional `permitSignature` //A permit signature of the tx. Only needed when previously signed (Not needed at the moment). +- @param `swapAll` //Bool indicating if the user wants to swap all the current collateral +- @param @optional `onBehalfOf` //The ethereum address for which user is swaping. It will default to the user address +- @param @optional `referralCode` //Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) +- @param @optional `useEthPath` //Boolean to indicate if the swap will use an ETH path. Defaults to false +*/ +const txs = await lendingPool.swapCollateral({ + user, + flash, + fromAsset, + fromAToken, + toAsset, + fromAmount, + toAmount, + maxSlippage, + permitSignature, + swapAll, + onBehalfOf, + referralCode, + useEthPath, +}); +// Submit transaction(s) as shown in Transaction Methods header +``` -### cancel +
-Cancels a Proposal. Callable by the \_guardian with relaxed conditions, or by anybody if the conditions of cancellation on the executor are fulfilled +
-- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to cancel +### repayWithCollateral -```ts gov2.cancel({ user, // string proposalId, // number }) ``` +Allows a borrower to repay the open debt with the borrower collateral -### queue +
+ Sample Code -Queue the proposal (If Proposal Succeeded) +```ts +import { + LendingPool, + InterestRate, + PermitSignature, +} from '@aave/contract-helpers'; -- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to queue +const lendingPool = new LendingPool(provider, { + LENDING_POOL: lendingPoolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); -```ts gov2.queue({ user, // string proposalId, // number }) ``` +/* +- @param `user` //The ethereum address that will liquidate the position +- @param `fromAsset` //The ethereum address of the asset you want to repay with (collateral) +- @param `fromAToken` //The ethereum address of the aToken of the asset you want to repay with (collateral) +- @param `assetToRepay` //The ethereum address of the asset you want to repay +- @param `repayWithAmount` //The amount of collateral you want to repay the debt with +- @param `repayAmount` //The amount of debt you want to repay +- @param `permitSignature` //A permit signature of the tx. Optional +- @param @optional `repayAllDebt` //Bool indicating if the user wants to repay all current debt. Defaults to false +- @param `rateMode` //Enum indicating the type of the interest rate of the collateral +- @param @optional `onBehalfOf` //The ethereum address for which user is swaping. It will default to the user address +- @param @optional `referralCode` //Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) +- @param @optional `flash` //If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false +- @param @optional `useEthPath` //Boolean to indicate if the swap will use an ETH path. Defaults to false +*/ +const txs = await lendingPool.repayWithCollateral({ + user, + fromAsset, + fromAToken, + assetToRepay, + repayWithAmount, + repayAmount, + permitSignature, + repayAllDebt, + rateMode, + onBehalfOf, + referralCode, + flash, + useEthPath, +}); +// Submit transaction(s) as shown in Transaction Methods header +``` -### execute +
-Execute the proposal (If Proposal Queued) +
-- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to execute +## Governance V2 -```ts gov2.execute({ user, // string proposalId, // number }) ``` +Example of how to use functions of the Aave governance service ### submitVote Function allowing msg.sender to vote for/against a proposal -- @param `user` The ethereum address that will create the proposal - @param `proposalId` Id of the proposal we want to vote - @param `support` Bool indicating if you are voting in favor (true) or against (false) +
+ Sample Code + +```ts +import { AaveGovernanceService } from '@aave/contract-helpers'; + +const governanceService = new AaveGovernanceService(rpcProvider, { + GOVERNANCE_ADDRESS: aaveGovernanceV2Address, + GOVERNANCE_HELPER_ADDRESS: aaveGovernanceV2HelperAddress, + ipfsGateway: IPFS_ENDPOINT, +}); + +/* +- @param `user` The ethereum address that will create the proposal +- @param `proposalId` Id of the proposal we want to vote +- @param `support` Bool indicating if you are voting in favor (true) or against (false) +*/ +const tx = governanceService.submitVote({ user, proposalId, support }); -```ts gov2.submitVote({ user, // string proposalId, // number support, // boolean }) ``` +// Submit transaction as shown in Transaction Methods header +``` + +
+ +
## Governance Delegation ### delegate -Method for the user to delegate voting `and` proposition power to the chosen address +Method for the user to delegate voting `and` proposition power to the chosen +address + +
+ Sample Code + +```ts +import { GovernancePowerDelegationTokenService } from '@aave/contract-helpers'; + +const powerDelegation = new GovernancePowerDelegationTokenService(rpcProvider); + +/* +- @param `user` The ethereum address that will create the proposal +- @param `delegatee` The ethereum address to which the user wants to delegate proposition power and voting power +- @param `governanceToken` The ethereum address of the governance token +*/ +const tx = powerDelegation.delegate({ user, delegatee, governanceToken }); + +// Submit transaction as shown in Transaction Methods header +``` -- @param `user` The ethereum address that will create the proposal - @param `delegatee` The ethereum address to which the user wants to delegate proposition power and voting power - @param `governanceToken` The ethereum address of the governance token +
-```ts powerDelegation.delegate({ user, // string delegatee, // string governanceToken // string }); ``` +
### delegateByType -Method for the user to delegate voting `or` proposition power to the chosen address +Method for the user to delegate voting `or` proposition power to the chosen +address -- @param `user` The ethereum address that will create the proposal - @param `delegatee` The ethereum address to which the user wants to delegate proposition power and voting power - @param `delegationType` The type of the delegation the user wants to do: voting power ('0') or proposition power ('1') - @param `governanceToken` The ethereum address of the governance token +
+ Sample Code -```ts powerDelegation.delegateByType({ user, // string delegatee, // string delegationType, // string governanceToken // string }); ``` +```ts +import { GovernancePowerDelegationTokenService } from '@aave/contract-helpers'; + +const powerDelegation = new GovernancePowerDelegationTokenService(rpcProvider); + +/* +- @param `user` The ethereum address that will create the proposal +- @param `delegatee` The ethereum address to which the user wants to delegate proposition power and voting power +- @param `delegationType` The type of the delegation the user wants to do: voting power ('0') or proposition power ('1') +- @param `governanceToken` The ethereum address of the governance token +*/ +const tx = powerDelegation.delegateByType({ + user, + delegatee, + delegationType, + governanceToken, +}); +// Submit transaction as shown in Transaction Methods header +``` -## Faucets +
-To use the testnet faucets which are compatible with Aave: +
-```ts import { TxBuilderV2, Network, Market } from '@aave/protocol-js' +## Faucets -const httpProvider = new Web3.providers.HttpProvider( process.env.ETHEREUM_URL || "https://kovan.infura.io/v3/" ); const txBuilder = new TxBuilderV2(Network.main, httpProvider); const faucet = txBuilder.faucetService; ``` +To use the testnet faucets which are compatible with Aave: ### mint -Mint tokens for the usage on the Aave protocol on the Kovan network. The amount of minted tokens is fixed and depends on the token +Mint tokens for the usage on the Aave protocol on a test network. The amount of +minted tokens is fixed and depends on the token -- @param `userAddress` The ethereum address of the wallet the minted tokens will go - @param `reserve` The ethereum address of the token you want to mint - @param `tokenSymbol` The symbol of the token you want to mint +
+ Sample Code -```ts faucet.mint({ userAddress, // string reserve, // string tokenSymbol, // string }); ``` +```ts +import { FaucetService } from '@aave/contract-helpers'; -## Usage +const faucetService = new FaucetService(provider, faucetAddress); -Here is a quick example to get you started: +/* +- @param `userAddress` The ethereum address of the wallet the minted tokens will go +- @param `reserve` The ethereum address of the token you want to mint +- @param `tokenSymbol` The symbol of the token you want to mint +*/ +const tx = faucet.mint({ userAddress, reserve, tokenSymbol }); -```ts import { PermissionManager } from '@aave/contract-helpers'; +// Submit transaction as shown in Transaction Methods header +``` -const instance = new PermissionManager({ provider: rpcProvider, permissionManagerAddress: permissionManagerAddress, }); const permissions = await instance.getHumanizedUserPermissions(walletAddress); ``` -```` +
From f7345f71fef1b80aec4b6aaf88a8aaeb92df58f2 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Tue, 18 Jan 2022 23:12:12 -0600 Subject: [PATCH 3/9] feat: add V3 transaction methods --- README.md | 817 ++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 695 insertions(+), 122 deletions(-) diff --git a/README.md b/README.md index 82d67c89..41090093 100644 --- a/README.md +++ b/README.md @@ -26,8 +26,11 @@ Aave utilities are available as npm packages, ```sh // with npm +npm install --save ethers // peer dependency npm install @aave/contract-helpers @aave/math-utils + // with yarn +yarn add --dev ethers // peer dependency yarn add @aave/contract-helpers @aave/math-utils ``` @@ -52,15 +55,15 @@ yarn add @aave/contract-helpers @aave/math-utils - [supply](#supply) - [signERC20Approval](#signERC20Approval) - [supplyWithPermit](#supply-with-permit) - - [borrow](#borrow-v3) - - [repay](#repay-v3) + - [borrow](<#borrow-(v3)>) + - [repay](<#repay-(v3)>) - [repayWithATokens](#repayWithATokens) - - [withdraw](#withdraw-v3) - - [swapBorrowRateMode](#swapBorrowRateMode-v3) - - [setUsageAsCollateral](#setUsageAsCollateral-v3) - - [liquidationCall](#liquidationCall-v3) - - [swapCollateral](#swapCollateral-v3) - - [repayWithCollateral](#repayWithCollateral-v3) + - [withdraw](<#withdraw-(v3)>) + - [swapBorrowRateMode](<#swapBorrowRateMode-(v3)>) + - [setUsageAsCollateral](<#setUsageAsCollateral-(v3)>) + - [liquidationCall](<#liquidationCall-(v3)>) + - [swapCollateral](<#swapCollateral-(v3)>) + - [repayWithCollateral](<#repayWithCollateral-(v3)>) - [setUserEMode](#setUserEMode) - c. [Lending Pool V2](#lending-pool-v2) - [deposit](#deposit) @@ -554,6 +557,577 @@ const txResponse = await signer.sendTransaction({ ## Pool V3 +Transaction methods to perform actions on the V3 Pool contract + +### supply + +Formerly `deposit`, supply the underlying asset into the Pool reserve. For every +token that is supplied, a corresponding amount of aTokens is minted + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `amount` The amount to be deposited +- @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.supply({ + user, + reserve, + amount, + onBehalfOf, +}); + +// If the user has not appoved the pool contract to spend their tokens, txs will also contain two transactions: approve and supply. These approval and supply transactions can be submitted just as in V2,OR you can skip the first approval transaction with a gasless signature by using signERC20Approval -> supplyWithPermit which are documented below + +// If there is no approval transaction, then supply() can called without the need for an approval or signature + +// Submit the transaction(s) as shown in Transaction Methods header +``` + +
+ +
+ +### signERC20Approval + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `amount` The amount to be deposited +*/ +const dataToSignPromise: string = await pool.signERC20Approval({ + user, + reserve, + amount, +}); + +const signature = await provider.send('eth_signTypedData_v4', [ + currentAccount, + dataToSign, +]); + +// This signature can now be passed into the supplyWithPermit() function below +``` + +
+ +
+ +### supplyWithPermit + +Same underlying method as `supply` but uses a signature based approval passed as +a paramter. + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `amount` The amount to be deposited +- @param `signature` Signature approving Pool to spend user funds, from signERC20Approval() +- @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.supplyWithPermit({ + user, + reserve, + amount, + signature, + onBehalfOf, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ +### borrow (V3) + +Borrow an `amount` of `reserve` asset. + +User must have a collaterised position (i.e. aTokens in their wallet) + +
+ Sample Code + +```ts +import { Pool, InterestRate } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that repays +- @param `reserve` The ethereum address of the reserve on which the user borrowed +- @param `amount` The amount to repay, or (-1) if the user wants to repay everything +- @param `interestRateMode` // Whether the borrow will incur a stable (InterestRate.Stable) or variable (InterestRate.Variable) interest rate +- @param @optional `onBehalfOf` The ethereum address for which user is repaying. It will default to the user address +*/ +const txs: EthereumTransactionTypeExtended[] = lendingPool.repay({ + user, + reserve, + amount, + interestRateMode, + onBehalfOf, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ +### repay (V3) + +Repays a borrow on the specific reserve, for the specified amount (or for the +whole amount, if (-1) is specified). the target user is defined by `onBehalfOf`. +If there is no repayment on behalf of another account, `onBehalfOf` must be +equal to `user` + +If the Pool is not approved to spend `user` funds, an approval transaction will +also be returned + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `amount` The amount to be deposited +- @param `interestRateMode` // Whether stable (InterestRate.Stable) or variable (InterestRate.Variable) debt will be repaid +- @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.repay({ + user, + reserve, + amount, + interestRateMode, + onBehalfOf, +}); + +// If the user has not appoved the pool contract to spend their tokens, txs will also contain two transactions: approve and repay. This approval transaction can be submitted just as in V2, OR you approve with a gasless signature by using signERC20Approval -> supplyWithPermit which are documented below + +// If there is no approval transaction, then repay() can called without the need for an approval or signature + +// Submit transaction(s) as shown in Transaction Methods header +``` + +
+ +
+ +### repayWithPermit + +Same underlying method as `repay` but uses a signature based approval passed as +a paramter. + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `amount` The amount to be deposited +- @param `signature` Signature approving Pool to spend user funds, from signERC20Approval() +- @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.supplyWithPermit({ + user, + reserve, + amount, + signature, + onBehalfOf, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ +### repayWithATokens + +Repays a borrow on the specific reserve, for the specified amount, deducting +funds from a users aToken balance instead of the underlying balance. To repay +the max debt amount or max aToken balance without dust (whichever is lowest), +set the amount to -1 + +There is no need for an approval or signature when repaying with aTokens + +
+ Sample Code + +```ts +import { Pool, InterestRate } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `amount` The amount to be deposited, -1 to repay max aToken balance or max debt balance without dust (whichever is lowest) +- @param `reserve` The ethereum address of the reserve +- @param `rateMode` The debt type to repay, stable (InterestRate.Stable) or variable (InterestRate.Variable) +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.repayWithATokens({ + user, + amount, + reserve, + reateMode, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ +### withdraw (V3) + +Withdraws the underlying asset of an aToken asset. + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `amount` The amount to be deposited +- @param `aTokenAddress` The aToken to redeem for underlying asset +- @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.withdraw({ + user, + reserve, + amount, + aTokenAddress, + onBehalfOf, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ +### swapBorrowRateMode (V3) + +Borrowers can use this function to swap between stable and variable borrow rate +modes + +
+ Sample Code + +```ts +import { Pool, InterestRate } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `interestRateMode` The rate mode to swap to, stable (InterestRate.Stable) or variable (InterestRate.Variable) +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.swapBorrowRateMode({ + user, + reserve, + amount, + onBehalfOf, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ +### setUsageAsCollateral (V3) + +Allows depositors to enable or disable a specific deposit as collateral + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `reserve` The ethereum address of the reserve +- @param `usageAsCollateral` Boolean, true if the user wants to use the deposit as collateral, false otherwise +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.setUsageAsCollateral({ + user, + reserve, + usageAsCollateral, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ +### liquidationCall (V3) + +Users can invoke this function to liquidate an undercollateralized position + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `liquidator` The ethereum address that will liquidate the position +- @param `liquidatedUser` The address of the borrower +- @param `debtReserve` The ethereum address of the principal reserve +- @param `collateralReserve` The address of the collateral to liquidated +- @param `purchaseAmount` The amount of principal that the liquidator wants to repay +- @param @optional `getAToken` Boolean to indicate if the user wants to receive the aToken instead of the asset. Defaults to false +*/ +const txs: EthereumTransactionTypeExtended[] = lendingPool.liquidationCall({ + liquidator, + liquidatedUser, + debtReserve, + collateralReserve, + purchaseAmount, + getAToken, +}); + +// Submit transaction(s) as shown in Transaction Methods header +``` + +
+ +
+ +### swapCollateral (V3) + +Utilizes flashloan to swap to a different collateral asset + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will liquidate the position +- @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false +- @param `fromAsset` The ethereum address of the asset you want to swap +- @param `fromAToken` The ethereum address of the aToken of the asset you want to swap +- @param `toAsset` The ethereum address of the asset you want to swap to (get) +- @param `fromAmount` The amount you want to swap +- @param `toAmount` The amount you want to get after the swap +- @param `maxSlippage` The max slippage that the user accepts in the swap +- @param @optional `permitSignature` A permit signature of the tx. Only needed when previously signed (Not needed at the moment). +- @param `swapAll` Bool indicating if the user wants to swap all the current collateral +- @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address +- @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) +- @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false +*/ +const txs: EthereumTransactionTypeExtended[] = await lendingPool.swapCollateral( + { + user, + flash, + fromAsset, + fromAToken, + toAsset, + fromAmount, + toAmount, + maxSlippage, + permitSignature, + swapAll, + onBehalfOf, + referralCode, + useEthPath, + }, +); + +// Submit transaction(s) as shown in Transaction Methods header +``` + +
+ +
+ +### repayWithCollateral (V3) + +Allows a borrower to repay the open debt with their collateral + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will liquidate the position +- @param `fromAsset` The ethereum address of the asset you want to repay with (collateral) +- @param `fromAToken` The ethereum address of the aToken of the asset you want to repay with (collateral) +- @param `assetToRepay` The ethereum address of the asset you want to repay +- @param `repayWithAmount` The amount of collateral you want to repay the debt with +- @param `repayAmount` The amount of debt you want to repay +- @param `permitSignature` A permit signature of the tx. Optional +- @param @optional `repayAllDebt` Bool indicating if the user wants to repay all current debt. Defaults to false +- @param `rateMode` //Enum indicating the type of the interest rate of the collateral +- @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address +- @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) +- @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false +- @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false +*/ +const txs: EthereumTransactionTypeExtended[] = + await lendingPool.repayWithCollateral({ + user, + fromAsset, + fromAToken, + assetToRepay, + repayWithAmount, + repayAmount, + permitSignature, + repayAllDebt, + rateMode, + onBehalfOf, + referralCode, + flash, + useEthPath, + }); + +// Submit transaction(s) as shown in Transaction Methods header +``` + +
+ +
+ +### setUserEMode + +Function to enable eMode on a user account IF conditions are met: + +To enable, pass `categoryId` of desired eMode (1 = stablecoins), can only be +enabled if a users currently borrowed assests are ALL within this eMode category +To disable, pass `categoryId` of 0, can only be disabled if new LTV will not +leave user undercollateralized + +
+ Sample Code + +```ts +import { Pool } from '@aave/contract-helpers'; + +const pool = new Pool(provider, { + POOL: poolAddress, + WETH_GATEWAY: wethGatewayAddress, +}); + +/* +- @param `user` The ethereum address that will make the deposit +- @param `categoryId` number representing the eMode to switch to, 0 = disable, 1 = stablecoins +*/ +const txs: EthereumTransactionTypeExtended[] = await pool.setUserEMode({ + user, + categoryId, +}); + +// Submit transaction[0] as shown in Transaction Methods header +``` + +
+ +
+ ## Lending Pool V2 Object that contains all the necessary methods to create Aave V2 lending pool @@ -572,8 +1146,6 @@ import { LendingPool } from '@aave/contract-helpers'; const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, WETH_GATEWAY: wethGatewayAddress, }); @@ -583,7 +1155,12 @@ const lendingPool = new LendingPool(provider, { - @param `amount` The amount to be deposited - @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address */ -const txs = await lendingPool.deposit({ user, reserve, amount, onBehalfOf }); +const txs: EthereumTransactionTypeExtended[] = await lendingPool.deposit({ + user, + reserve, + amount, + onBehalfOf, +}); // Submit transaction(s) as shown in Transaction Methods header ``` @@ -608,20 +1185,18 @@ import { LendingPool, InterestRate } from '@aave/contract-helpers'; const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `user` //The ethereum address that will receive the borrowed amount -- @param `reserve` //The ethereum address of the reserve asset -- @param `amount` //The amount to be borrowed, in human readable units (e.g. 2.5 ETH) -- @param `interestRateMode`//Whether the borrow will incur a stable or variable interest rate (1 | 2) -- @param @optional `debtTokenAddress` //The ethereum address of the debt token of the asset you want to borrow. Only needed if the reserve is ETH mock address -- @param @optional `onBehalfOf` //The ethereum address for which user is borrowing. It will default to the user address +- @param `user` The ethereum address that will receive the borrowed amount +- @param `reserve` The ethereum address of the reserve asset +- @param `amount` The amount to be borrowed, in human readable units (e.g. 2.5 ETH) +- @param `interestRateMode`//Whether the borrow will incur a stable (InterestRate.Stable) or variable (InterestRate.Variable) interest rate +- @param @optional `debtTokenAddress` The ethereum address of the debt token of the asset you want to borrow. Only needed if the reserve is ETH mock address +- @param @optional `onBehalfOf` The ethereum address for which user is borrowing. It will default to the user address */ -const txs = await lendingPool.borrow({ +const txs: EthereumTransactionTypeExtended[] = await lendingPool.borrow({ user, reserve, amount, @@ -655,19 +1230,17 @@ import { LendingPool, InterestRate } from '@aave/contract-helpers'; const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `user` //The ethereum address that repays -- @param `reserve` //The ethereum address of the reserve on which the user borrowed -- @param `amount` //The amount to repay, or (-1) if the user wants to repay everything -- @param `interestRateMode` //Whether the borrow will incur a stable or variable interest rate (1 | 2) -- @param @optional `onBehalfOf` //The ethereum address for which user is repaying. It will default to the user address +- @param `user` The ethereum address that repays +- @param `reserve` The ethereum address of the reserve on which the user borrowed +- @param `amount` The amount to repay, or (-1) if the user wants to repay everything +- @param `interestRateMode` // Whether stable (InterestRate.Stable) or variable (InterestRate.Variable) debt will be repaid +- @param @optional `onBehalfOf` The ethereum address for which user is repaying. It will default to the user address */ -const txs = lendingPool.repay({ +const txs: EthereumTransactionTypeExtended[] = lendingPool.repay({ user, reserve, amount, @@ -694,19 +1267,17 @@ import { LendingPool } from '@aave/contract-helpers'; const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `user` //The ethereum address that will receive the aTokens -- @param `reserve` //The ethereum address of the reserve asset -- @param `amount` //The amount of aToken being redeemed -- @param @optional `aTokenAddress` //The ethereum address of the aToken. Only needed if the reserve is ETH mock address -- @param @optional `onBehalfOf` //The amount of aToken being redeemed. It will default to the user address +- @param `user` The ethereum address that will receive the aTokens +- @param `reserve` The ethereum address of the reserve asset +- @param `amount` The amount of aToken being redeemed +- @param @optional `aTokenAddress` The ethereum address of the aToken. Only needed if the reserve is ETH mock address +- @param @optional `onBehalfOf` The amount of aToken being redeemed. It will default to the user address */ -const txs = lendingPool.withdraw({ +const txs: EthereumTransactionTypeExtended[] = lendingPool.withdraw({ user, reserve, amount, @@ -734,17 +1305,18 @@ import { LendingPool, InterestRate } from '@aave/contract-helpers'; const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, - WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `user` //The ethereum address that wants to swap rate modes -- @param `reserve` //The address of the reserve on which the user borrowed -- @param `interestRateMode` //Whether the borrow will incur a stable or variable interest rate (1 | 2) +- @param `user` The ethereum address that wants to swap rate modes +- @param `reserve` The address of the reserve on which the user borrowed +- @param `interestRateMode` //Whether the borrow will incur a stable (InterestRate.Stable) or variable (InterestRate.Variable) interest rate */ -const txs = lendingPool.swapBorrowRateMode({ user, reserve, interestRateMode }); +const txs: EthereumTransactionTypeExtended[] = lendingPool.swapBorrowRateMode({ + user, + reserve, + interestRateMode, +}); // Submit transaction(s) as shown in Transaction Methods header ``` @@ -754,7 +1326,7 @@ const txs = lendingPool.swapBorrowRateMode({ user, reserve, interestRateMode }); ### setUsageAsCollateral -Allows depositors to enable or disable a specific deposit as collateral. +Allows depositors to enable or disable a specific deposit as collateral
Sample Code @@ -764,21 +1336,20 @@ import { LendingPool, InterestRate } from '@aave/contract-helpers'; const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, - WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `user` //The ethereum address that enables or disables the deposit as collateral -- @param `reserve` //The ethereum address of the reserve -- @param `useAsCollateral` //True if the user wants to use the deposit as collateral, false otherwise. +- @param `user` The ethereum address that enables or disables the deposit as collateral +- @param `reserve` The ethereum address of the reserve +- @param `useAsCollateral` Boolean, true if the user wants to use the deposit as collateral, false otherwise */ -const txs = lendingPool.setUsageAsCollateral({ - user, - reserve, - usageAsCollateral, -}); +const txs: EthereumTransactionTypeExtended[] = lendingPool.setUsageAsCollateral( + { + user, + reserve, + usageAsCollateral, + }, +); // Submit transaction(s) as shown in Transaction Methods header ``` @@ -800,20 +1371,18 @@ import { LendingPool } from '@aave/contract-helpers'; const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `liquidator` //The ethereum address that will liquidate the position -- @param `liquidatedUser` //The address of the borrower -- @param `debtReserve` //The ethereum address of the principal reserve -- @param `collateralReserve` //The address of the collateral to liquidated -- @param `purchaseAmount` //The amount of principal that the liquidator wants to repay -- @param @optional `getAToken` //Boolean to indicate if the user wants to receive the aToken instead of the asset. Defaults to false +- @param `liquidator` The ethereum address that will liquidate the position +- @param `liquidatedUser` The address of the borrower +- @param `debtReserve` The ethereum address of the principal reserve +- @param `collateralReserve` The address of the collateral to liquidated +- @param `purchaseAmount` The amount of principal that the liquidator wants to repay +- @param @optional `getAToken` Boolean to indicate if the user wants to receive the aToken instead of the asset. Defaults to false */ -const txs = lendingPool.liquidationCall({ +const txs: EthereumTransactionTypeExtended[] = lendingPool.liquidationCall({ liquidator, liquidatedUser, debtReserve, @@ -821,6 +1390,7 @@ const txs = lendingPool.liquidationCall({ purchaseAmount, getAToken, }); + // Submit transaction(s) as shown in Transaction Methods header ``` @@ -844,41 +1414,43 @@ import { const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, - REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `user` //The ethereum address that will liquidate the position -- @param @optional `flash` //If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false -- @param `fromAsset` //The ethereum address of the asset you want to swap -- @param `fromAToken` //The ethereum address of the aToken of the asset you want to swap -- @param `toAsset` //The ethereum address of the asset you want to swap to (get) -- @param `fromAmount` //The amount you want to swap -- @param `toAmount` //The amount you want to get after the swap -- @param `maxSlippage` //The max slippage that the user accepts in the swap -- @param @optional `permitSignature` //A permit signature of the tx. Only needed when previously signed (Not needed at the moment). -- @param `swapAll` //Bool indicating if the user wants to swap all the current collateral -- @param @optional `onBehalfOf` //The ethereum address for which user is swaping. It will default to the user address -- @param @optional `referralCode` //Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) -- @param @optional `useEthPath` //Boolean to indicate if the swap will use an ETH path. Defaults to false +- @param `user` The ethereum address that will liquidate the position +- @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false +- @param `fromAsset` The ethereum address of the asset you want to swap +- @param `fromAToken` The ethereum address of the aToken of the asset you want to swap +- @param `toAsset` The ethereum address of the asset you want to swap to (get) +- @param `fromAmount` The amount you want to swap +- @param `toAmount` The amount you want to get after the swap +- @param `maxSlippage` The max slippage that the user accepts in the swap +- @param @optional `permitSignature` A permit signature of the tx. Only needed when previously signed (Not needed at the moment). +- @param `swapAll` Bool indicating if the user wants to swap all the current collateral +- @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address +- @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) +- @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false */ -const txs = await lendingPool.swapCollateral({ - user, - flash, - fromAsset, - fromAToken, - toAsset, - fromAmount, - toAmount, - maxSlippage, - permitSignature, - swapAll, - onBehalfOf, - referralCode, - useEthPath, -}); +const txs: EthereumTransactionTypeExtended[] = await lendingPool.swapCollateral( + { + user, + flash, + fromAsset, + fromAToken, + toAsset, + fromAmount, + toAmount, + maxSlippage, + permitSignature, + swapAll, + onBehalfOf, + referralCode, + useEthPath, + }, +); + // Submit transaction(s) as shown in Transaction Methods header ``` @@ -888,7 +1460,7 @@ const txs = await lendingPool.swapCollateral({ ### repayWithCollateral -Allows a borrower to repay the open debt with the borrower collateral +Allows a borrower to repay the open debt with their collateral
Sample Code @@ -903,40 +1475,41 @@ import { const lendingPool = new LendingPool(provider, { LENDING_POOL: lendingPoolAddress, REPAY_WITH_COLLATERAL_ADAPTER: repayWithCollateralAddress, - SWAP_COLLATERAL_ADAPTER: swapCollateralAdapterAddress, WETH_GATEWAY: wethGatewayAddress, }); /* -- @param `user` //The ethereum address that will liquidate the position -- @param `fromAsset` //The ethereum address of the asset you want to repay with (collateral) -- @param `fromAToken` //The ethereum address of the aToken of the asset you want to repay with (collateral) -- @param `assetToRepay` //The ethereum address of the asset you want to repay -- @param `repayWithAmount` //The amount of collateral you want to repay the debt with -- @param `repayAmount` //The amount of debt you want to repay -- @param `permitSignature` //A permit signature of the tx. Optional -- @param @optional `repayAllDebt` //Bool indicating if the user wants to repay all current debt. Defaults to false +- @param `user` The ethereum address that will liquidate the position +- @param `fromAsset` The ethereum address of the asset you want to repay with (collateral) +- @param `fromAToken` The ethereum address of the aToken of the asset you want to repay with (collateral) +- @param `assetToRepay` The ethereum address of the asset you want to repay +- @param `repayWithAmount` The amount of collateral you want to repay the debt with +- @param `repayAmount` The amount of debt you want to repay +- @param `permitSignature` A permit signature of the tx. Optional +- @param @optional `repayAllDebt` Bool indicating if the user wants to repay all current debt. Defaults to false - @param `rateMode` //Enum indicating the type of the interest rate of the collateral -- @param @optional `onBehalfOf` //The ethereum address for which user is swaping. It will default to the user address -- @param @optional `referralCode` //Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) -- @param @optional `flash` //If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false -- @param @optional `useEthPath` //Boolean to indicate if the swap will use an ETH path. Defaults to false +- @param @optional `onBehalfOf` The ethereum address for which user is swaping. It will default to the user address +- @param @optional `referralCode` Integrators are assigned a referral code and can potentially receive rewards. It defaults to 0 (no referrer) +- @param @optional `flash` If the transaction will be executed through a flasloan(true) or will be done directly through the adapters(false). Defaults to false +- @param @optional `useEthPath` Boolean to indicate if the swap will use an ETH path. Defaults to false */ -const txs = await lendingPool.repayWithCollateral({ - user, - fromAsset, - fromAToken, - assetToRepay, - repayWithAmount, - repayAmount, - permitSignature, - repayAllDebt, - rateMode, - onBehalfOf, - referralCode, - flash, - useEthPath, -}); +const txs: EthereumTransactionTypeExtended[] = + await lendingPool.repayWithCollateral({ + user, + fromAsset, + fromAToken, + assetToRepay, + repayWithAmount, + repayAmount, + permitSignature, + repayAllDebt, + rateMode, + onBehalfOf, + referralCode, + flash, + useEthPath, + }); + // Submit transaction(s) as shown in Transaction Methods header ``` From f8e225008947a16fc4277344e15b116ded316f78 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Tue, 18 Jan 2022 23:12:59 -0600 Subject: [PATCH 4/9] feat: update layout of data formatting methods --- README.md | 103 ++++++++++++++++++++++++------------------------------ 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/README.md b/README.md index 41090093..adaa0112 100644 --- a/README.md +++ b/README.md @@ -299,24 +299,19 @@ Examples of hooks for fetching data with these queries are located ## Reserve Data -Formatted reserve data is an array of tokens in the Aave market, including -supply, borrow rates, configuration, +Formatted reserve data is an array of tokens in the Aave market, containing +realtime, human-readable data above asset configuration (maxLtv, +liquidationThreshold, usageAsCollateral, etc.) and current status (rates, +liquidity, utilization, etc.) -### formatReserves - -Description +There are two formatter functions, one with incentives data and one without. +Both of these functions take input data from the +[fetching protocol data](#fetching-protocol-data) section -
- Parameters - -```ts -- @param `reserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` -- @param `currentTimestamp` //Current UNIX timestamp in seconds -- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` -``` +### formatReserves -
+formatReserves returns an array of formatted configuration and status data for +each reserve in an Aave market
Sample Code @@ -331,6 +326,12 @@ const baseCurrencyData = reserves.baseCurrencyData; const currentTimestamp = Math.round(new Date().getTime() / 1000); +/* +- @param `reserves` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` +- @param `currentTimestamp` Current UNIX timestamp in seconds +- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +*/ const formattedPoolReserves = formatReserves({ reserves: reservesArray, currentTimestamp, @@ -346,18 +347,9 @@ const formattedPoolReserves = formatReserves({ ### formatReservesAndIncentives -
- Parameters - -```ts -- @param `reserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` -- @param `currentTimestamp` //Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) -- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` -- @param `reserveIncentives` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` -``` - -
+formatReservesAndIncentives returns an array of formatted configuration and +status data plus an object with supply, variable borrow, and stable borrow +incentives for each reserve in an Aave market
Sample Code @@ -372,6 +364,13 @@ const baseCurrencyData = reserves.baseCurrencyData; const currentTimestamp = Math.round(new Date().getTime() / 1000); +/* +- @param `reserves` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` +- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `reserveIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` +*/ const formattedPoolReserves = formatReservesAndIncentives({ reserves: reservesArray, currentTimestamp, @@ -388,26 +387,15 @@ const formattedPoolReserves = formatReservesAndIncentives({ ## User Data -Description +Formatted user data is an object containing cumulative metrics (healthFactor, +totalLiquidity, totalBorrows, etc.) and an array of formatted reserve data plus +user holdings (aTokens, debtTokens) for each reserve in an Aave market ### formatUserSummary Returns formatted summary of Aave user portfolio including: array of holdings, total liquidity, total collateral, total borrows, liquidation threshold, health -factor, and available borrowing power. - -
- Parameters - -```ts -- @param `currentTimestamp` //Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) -- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` -- @param `userReserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` -- @param `userEmodeCategoryId` //Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` -``` - -
+factor, and available borrowing power
Sample Code @@ -441,6 +429,13 @@ if (userReservesArray && reservesArray.length) { }); } +/* +- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `userReserves` Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` +- @param `userEmodeCategoryId` Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` +*/ const userSummary = formatUserSummaryAndIncentives({ currentTimestamp, marketReferencePriceInUsd: baseCurrencyData.marketReferenceCurrencyPriceInUsd, @@ -461,21 +456,6 @@ Returns formatted summary of Aave user portfolio including: array of holdings, total liquidity, total collateral, total borrows, liquidation threshold, health factor, available borrowing power, and dictionary of claimable incentives -
- Parameters - -```ts -- @param `currentTimestamp` //Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) -- @param `marketReferencePriceInUsd` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` -- @param `marketReferenceCurrencyDecimals` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` -- @param `userReserves` //Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` -- @param `userEmodeCategoryId` //Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` -- @param `reserveIncentives` //Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` -- @param `userIncentives` //Input from [Fetching Protocol Data](#fetching-protocol-data), `userIncentives` -``` - -
-
Sample Code @@ -506,6 +486,15 @@ if (userReservesArray && reservesArray.length) { }); } +/* +- @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) +- @param `marketReferencePriceInUsd` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferencePriceInUsd` +- @param `marketReferenceCurrencyDecimals` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.baseCurrencyData.marketReferenceCurrencyDecimals` +- @param `userReserves` Input from [Fetching Protocol Data](#fetching-protocol-data), combination of `userReserves.userReserves` and `reserves.reservesArray` +- @param `userEmodeCategoryId` Input from [Fetching Protocol Data](#fetching-protocol-data), `userReserves.userEmodeCategoryId` +- @param `reserveIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserveIncentives` +- @param `userIncentives` Input from [Fetching Protocol Data](#fetching-protocol-data), `userIncentives` +*/ const userSummary = formatUserSummaryAndIncentives({ currentTimestamp, marketReferencePriceInUsd: baseCurrencyData.marketReferenceCurrencyPriceInUsd, From d39aef7ba2d5d32d65f341ab96fd510adea597e6 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Tue, 18 Jan 2022 23:36:16 -0600 Subject: [PATCH 5/9] fix: typos --- README.md | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index adaa0112..4740c0d4 100644 --- a/README.md +++ b/README.md @@ -26,11 +26,11 @@ Aave utilities are available as npm packages, ```sh // with npm -npm install --save ethers // peer dependency +npm install --save ethers npm install @aave/contract-helpers @aave/math-utils // with yarn -yarn add --dev ethers // peer dependency +yarn add --dev ethers yarn add @aave/contract-helpers @aave/math-utils ``` @@ -75,15 +75,12 @@ yarn add @aave/contract-helpers @aave/math-utils - [liquidationCall](#liquidationCall) - [swapCollateral](#swapCollateral) - [repayWithCollateral](#repayWithCollateral) - - d. [Flashloans](#flashloans) - - [V2](#flashloans-v2) - - [V3](#flashloans-v3) - - e. [Staking](#staking) + - d. [Staking](#staking) - [stake](#stake) - [redeem](#redeem) - [cooldown](#cooldown) - [claimRewards](#claimRewards) - - f. [Governance V2](#governancev2) + - e. [Governance V2](#governancev2) - [Governance](#governance) - [create](#create) - [cancel](#cancel) @@ -93,7 +90,7 @@ yarn add @aave/contract-helpers @aave/math-utils - [GovernanceDelegation](#governanceDelegation) - [delegate](#delegate) - [delegateByType](#delegateByType) - - g. [Faucets](#faucets) + - f. [Faucets](#faucets) - [mint](#mint)
@@ -305,7 +302,7 @@ liquidationThreshold, usageAsCollateral, etc.) and current status (rates, liquidity, utilization, etc.) There are two formatter functions, one with incentives data and one without. -Both of these functions take input data from the +Both require input data from the [fetching protocol data](#fetching-protocol-data) section ### formatReserves @@ -533,7 +530,6 @@ To send a transaction from this object: import { BigNumber } from 'ethers'; // initialize provider -// tx of type EthereumTransactionTypeExtended const extendedTxData = await tx.unsignedData(); const { from, ...txData } = extendedTxData; @@ -590,6 +586,11 @@ const txs: EthereumTransactionTypeExtended[] = await pool.supply({ ### signERC20Approval +This method is used to generate the raw signature data to be signed by the user. +Once generated, a function is called to trigger a signature request from the +users wallet. This signature can be passed a parameter to `supplyWithPermit` or +`repayWithPermit` in place of an approval transaction +
Sample Code @@ -606,7 +607,7 @@ const pool = new Pool(provider, { - @param `reserve` The ethereum address of the reserve - @param `amount` The amount to be deposited */ -const dataToSignPromise: string = await pool.signERC20Approval({ +const dataToSign: string = await pool.signERC20Approval({ user, reserve, amount, @@ -644,7 +645,7 @@ const pool = new Pool(provider, { - @param `user` The ethereum address that will make the deposit - @param `reserve` The ethereum address of the reserve - @param `amount` The amount to be deposited -- @param `signature` Signature approving Pool to spend user funds, from signERC20Approval() +- @param `signature` Signature approving Pool to spend user funds, received from signing output data of signERC20Approval() - @param @optional `onBehalfOf` The ethereum address for which user is depositing. It will default to the user address */ const txs: EthereumTransactionTypeExtended[] = await pool.supplyWithPermit({ From 1996e26d5cea2858646a8280917f3ca9637c2625 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Wed, 19 Jan 2022 23:00:28 -0600 Subject: [PATCH 6/9] feat: add governance transaction methods --- README.md | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 121 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4740c0d4..b9d0bd9e 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ yarn add @aave/contract-helpers @aave/math-utils - [supplyWithPermit](#supply-with-permit) - [borrow](<#borrow-(v3)>) - [repay](<#repay-(v3)>) + - [repayWithPermit](#repayWithPermit) - [repayWithATokens](#repayWithATokens) - [withdraw](<#withdraw-(v3)>) - [swapBorrowRateMode](<#swapBorrowRateMode-(v3)>) @@ -81,13 +82,11 @@ yarn add @aave/contract-helpers @aave/math-utils - [cooldown](#cooldown) - [claimRewards](#claimRewards) - e. [Governance V2](#governancev2) - - [Governance](#governance) - [create](#create) - [cancel](#cancel) - [queue](#queue) - [execute](#execute) - [submitVote](#submitVote) - - [GovernanceDelegation](#governanceDelegation) - [delegate](#delegate) - [delegateByType](#delegateByType) - f. [Faucets](#faucets) @@ -1511,6 +1510,126 @@ const txs: EthereumTransactionTypeExtended[] = Example of how to use functions of the Aave governance service +``` +import { + TxBuilderV2, + AaveGovernanceV2Interface, + GovernanceDelegationTokenInterface, +} from '@aave/protocol-js'; + +const httpProvider = new Web3.providers.HttpProvider( + process.env.ETHEREUM_URL || + "https://kovan.infura.io/v3/" +); +const txBuilder = new TxBuilderV2(Network.main, httpProvider); +const gov2 = txBuilder.aaveGovernanceV2Service; +const powerDelegation = txBuilder.governanceDelegationTokenService; +``` + +### create + +Creates a Proposal (needs to be validated by the Proposal Validator) + +```ts +import { AaveGovernanceService } from '@aave/contract-helpers'; + +const governanceService = new AaveGovernanceService(rpcProvider, { + GOVERNANCE_ADDRESS: aaveGovernanceV2Address, + GOVERNANCE_HELPER_ADDRESS: aaveGovernanceV2HelperAddress, + ipfsGateway: IPFS_ENDPOINT, +}); + +/* +- @param `user` The ethereum address that will create the proposal +- @param `targets` list of contracts called by proposal's associated transactions +- @param `values` list of value in wei for each propoposal's associated transaction +- @param `signatures` list of function signatures (can be empty) to be used when created the callData +- @param `calldatas` list of calldatas: if associated signature empty, calldata ready, else calldata is arguments +- @param `withDelegatecalls` boolean, true = transaction delegatecalls the taget, else calls the target +- @param `ipfsHash` IPFS hash of the proposal +- @param `executor` The ExecutorWithTimelock contract that will execute the proposal: ExecutorType.Short or ExecutorType.Long +*/ +const tx = governanceService.create({ + user, + targets, + values, + signatures, + calldatas, + withDelegatecalls, + ipfsHash, + executor, +}); + +// Submit transaction as shown in Transaction Methods header +``` + +### cancel + +Cancels a Proposal. Callable by the guardian with relaxed conditions, or by +anybody if the conditions of cancellation on the executor are fulfilled + +```ts +import { AaveGovernanceService } from '@aave/contract-helpers'; + +const governanceService = new AaveGovernanceService(rpcProvider, { + GOVERNANCE_ADDRESS: aaveGovernanceV2Address, + GOVERNANCE_HELPER_ADDRESS: aaveGovernanceV2HelperAddress, + ipfsGateway: IPFS_ENDPOINT, +}); + +/* +- @param `user` The ethereum address that will create the proposal +- @param `proposalId` Id of the proposal we want to queue +*/ +const tx = governanceService.cancel({ user, proposalId }); + +// Submit transaction as shown in Transaction Methods header +``` + +### queue + +Queue the proposal (If Proposal Succeeded) + +```ts +import { AaveGovernanceService } from '@aave/contract-helpers'; + +const governanceService = new AaveGovernanceService(rpcProvider, { + GOVERNANCE_ADDRESS: aaveGovernanceV2Address, + GOVERNANCE_HELPER_ADDRESS: aaveGovernanceV2HelperAddress, + ipfsGateway: IPFS_ENDPOINT, +}); + +/* +- @param `user` The ethereum address that will create the proposal +- @param `proposalId` Id of the proposal we want to queue +*/ +const tx = governanceService.queue({ user, proposalId }); + +// Submit transaction as shown in Transaction Methods header +``` + +### execute + +Execute the proposal (If Proposal Queued) + +```ts +import { AaveGovernanceService } from '@aave/contract-helpers'; + +const governanceService = new AaveGovernanceService(rpcProvider, { + GOVERNANCE_ADDRESS: aaveGovernanceV2Address, + GOVERNANCE_HELPER_ADDRESS: aaveGovernanceV2HelperAddress, + ipfsGateway: IPFS_ENDPOINT, +}); + +/* +- @param `user` The ethereum address that will create the proposal +- @param `proposalId` Id of the proposal we want to execute +*/ +const tx = governanceService.execute({ user, proposalId }); + +// Submit transaction as shown in Transaction Methods header +``` + ### submitVote Function allowing msg.sender to vote for/against a proposal @@ -1541,8 +1660,6 @@ const tx = governanceService.submitVote({ user, proposalId, support });
-## Governance Delegation - ### delegate Method for the user to delegate voting `and` proposition power to the chosen From 0d4e02b6d3d5131383e647ea0736d4b45ceda7b6 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Wed, 19 Jan 2022 23:19:42 -0600 Subject: [PATCH 7/9] feat: add submitting transactions section --- README.md | 195 +++++++++++++++++++++++++++++++----------------------- 1 file changed, 112 insertions(+), 83 deletions(-) diff --git a/README.md b/README.md index b9d0bd9e..90171f29 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ yarn add @aave/contract-helpers @aave/math-utils - [formatUserSummary](#formatUserSummary) - [formatUserSummaryAndIncentives](#formatUserSummaryAndIncentives) 2. [Transaction Methods](#transaction-methods) - - a. [Provider Setup](#provider-setup) + - a. [Submitting Transactions](#submitting-transactions) - b. [Pool V3](#pool-v3) - [supply](#supply) - [signERC20Approval](#signERC20Approval) @@ -515,9 +515,12 @@ and ethers provider Once initialized this sdk can be used to generate the transaction data needed to perform an action. If an approval is required, the method will return an array -with two transactions, or single transaction if no approval is needed +with two transactions, or single transaction if no approval is needed. -Transactions objects will be of this type: +## Submitting Transactions + +All transaction methods will return an array of transaction objects of this +type: ```ts import { EthereumTransactionTypeExtended } from '@aave/contract-helpers'; @@ -526,17 +529,20 @@ import { EthereumTransactionTypeExtended } from '@aave/contract-helpers'; To send a transaction from this object: ```ts -import { BigNumber } from 'ethers'; - -// initialize provider - -const extendedTxData = await tx.unsignedData(); -const { from, ...txData } = extendedTxData; -const signer = provider.getSigner(from); -const txResponse = await signer.sendTransaction({ - ...txData, - value: txData.value ? BigNumber.from(txData.value) : undefined, -}); +import { BigNumber, providers } from 'ethers'; + +function submitTransaction({ + provider: providers.Web3Provider, + tx: EthereumTransactionTypeExtended +}){ + const extendedTxData = await tx.unsignedData(); + const { from, ...txData } = extendedTxData; + const signer = provider.getSigner(from); + const txResponse = await signer.sendTransaction({ + ...txData, + value: txData.value ? BigNumber.from(txData.value) : undefined, + }); +} ``` ## Pool V3 @@ -575,10 +581,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.supply({ // If the user has not appoved the pool contract to spend their tokens, txs will also contain two transactions: approve and supply. These approval and supply transactions can be submitted just as in V2,OR you can skip the first approval transaction with a gasless signature by using signERC20Approval -> supplyWithPermit which are documented below // If there is no approval transaction, then supply() can called without the need for an approval or signature - -// Submit the transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +

@@ -654,10 +660,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.supplyWithPermit({ signature, onBehalfOf, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +

@@ -686,17 +692,17 @@ const pool = new Pool(provider, { - @param `interestRateMode` // Whether the borrow will incur a stable (InterestRate.Stable) or variable (InterestRate.Variable) interest rate - @param @optional `onBehalfOf` The ethereum address for which user is repaying. It will default to the user address */ -const txs: EthereumTransactionTypeExtended[] = lendingPool.repay({ +const txs: EthereumTransactionTypeExtended[] = pool.Borrow({ user, reserve, amount, interestRateMode, onBehalfOf, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +

@@ -740,10 +746,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.repay({ // If the user has not appoved the pool contract to spend their tokens, txs will also contain two transactions: approve and repay. This approval transaction can be submitted just as in V2, OR you approve with a gasless signature by using signERC20Approval -> supplyWithPermit which are documented below // If there is no approval transaction, then repay() can called without the need for an approval or signature - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +

@@ -778,10 +784,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.supplyWithPermit({ signature, onBehalfOf, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +

@@ -818,10 +824,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.repayWithATokens({ reserve, reateMode, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +

@@ -855,10 +861,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.withdraw({ aTokenAddress, onBehalfOf, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +

@@ -890,10 +896,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.swapBorrowRateMode({ amount, onBehalfOf, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -923,10 +929,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.setUsageAsCollateral({ reserve, usageAsCollateral, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -962,10 +968,10 @@ const txs: EthereumTransactionTypeExtended[] = lendingPool.liquidationCall({ purchaseAmount, getAToken, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1018,10 +1024,10 @@ const txs: EthereumTransactionTypeExtended[] = await lendingPool.swapCollateral( useEthPath, }, ); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1073,10 +1079,10 @@ const txs: EthereumTransactionTypeExtended[] = flash, useEthPath, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1109,10 +1115,10 @@ const txs: EthereumTransactionTypeExtended[] = await pool.setUserEMode({ user, categoryId, }); - -// Submit transaction[0] as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1150,10 +1156,10 @@ const txs: EthereumTransactionTypeExtended[] = await lendingPool.deposit({ amount, onBehalfOf, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1194,10 +1200,10 @@ const txs: EthereumTransactionTypeExtended[] = await lendingPool.borrow({ onBehalfOf, referralCode, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1236,10 +1242,10 @@ const txs: EthereumTransactionTypeExtended[] = lendingPool.repay({ interestRateMode, onBehalfOf, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1273,10 +1279,10 @@ const txs: EthereumTransactionTypeExtended[] = lendingPool.withdraw({ aTokenAddress, onBehalfOf, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1306,9 +1312,10 @@ const txs: EthereumTransactionTypeExtended[] = lendingPool.swapBorrowRateMode({ reserve, interestRateMode, }); -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1339,9 +1346,10 @@ const txs: EthereumTransactionTypeExtended[] = lendingPool.setUsageAsCollateral( usageAsCollateral, }, ); -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1379,10 +1387,10 @@ const txs: EthereumTransactionTypeExtended[] = lendingPool.liquidationCall({ purchaseAmount, getAToken, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1439,10 +1447,10 @@ const txs: EthereumTransactionTypeExtended[] = await lendingPool.swapCollateral( useEthPath, }, ); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1498,10 +1506,10 @@ const txs: EthereumTransactionTypeExtended[] = flash, useEthPath, }); - -// Submit transaction(s) as shown in Transaction Methods header ``` +Submit transaction(s) as shown [here](#submitting-transactions) +
@@ -1510,26 +1518,27 @@ const txs: EthereumTransactionTypeExtended[] = Example of how to use functions of the Aave governance service -``` -import { - TxBuilderV2, - AaveGovernanceV2Interface, - GovernanceDelegationTokenInterface, -} from '@aave/protocol-js'; +```ts +import { AaveGovernanceService } from '@aave/contract-helpers'; const httpProvider = new Web3.providers.HttpProvider( - process.env.ETHEREUM_URL || - "https://kovan.infura.io/v3/" + process.env.ETHEREUM_URL || 'https://kovan.infura.io/v3/', ); -const txBuilder = new TxBuilderV2(Network.main, httpProvider); -const gov2 = txBuilder.aaveGovernanceV2Service; -const powerDelegation = txBuilder.governanceDelegationTokenService; + +const governanceService = new AaveGovernanceService(httpProvider, { + GOVERNANCE_ADDRESS: aaveGovernanceV2Address, + GOVERNANCE_HELPER_ADDRESS: aaveGovernanceV2HelperAddress, + ipfsGateway: IPFS_ENDPOINT, +}); ``` ### create Creates a Proposal (needs to be validated by the Proposal Validator) +
+ Sample Code + ```ts import { AaveGovernanceService } from '@aave/contract-helpers'; @@ -1559,15 +1568,21 @@ const tx = governanceService.create({ ipfsHash, executor, }); - -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) + +
+
+ ### cancel Cancels a Proposal. Callable by the guardian with relaxed conditions, or by anybody if the conditions of cancellation on the executor are fulfilled +
+ Sample Code + ```ts import { AaveGovernanceService } from '@aave/contract-helpers'; @@ -1582,10 +1597,13 @@ const governanceService = new AaveGovernanceService(rpcProvider, { - @param `proposalId` Id of the proposal we want to queue */ const tx = governanceService.cancel({ user, proposalId }); - -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) + +
+
+ ### queue Queue the proposal (If Proposal Succeeded) @@ -1604,14 +1622,21 @@ const governanceService = new AaveGovernanceService(rpcProvider, { - @param `proposalId` Id of the proposal we want to queue */ const tx = governanceService.queue({ user, proposalId }); - -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) + + + +
+ ### execute Execute the proposal (If Proposal Queued) +
+ Sample Code + ```ts import { AaveGovernanceService } from '@aave/contract-helpers'; @@ -1626,10 +1651,13 @@ const governanceService = new AaveGovernanceService(rpcProvider, { - @param `proposalId` Id of the proposal we want to execute */ const tx = governanceService.execute({ user, proposalId }); - -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) + +
+
+ ### submitVote Function allowing msg.sender to vote for/against a proposal @@ -1652,10 +1680,10 @@ const governanceService = new AaveGovernanceService(rpcProvider, { - @param `support` Bool indicating if you are voting in favor (true) or against (false) */ const tx = governanceService.submitVote({ user, proposalId, support }); - -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1679,10 +1707,10 @@ const powerDelegation = new GovernancePowerDelegationTokenService(rpcProvider); - @param `governanceToken` The ethereum address of the governance token */ const tx = powerDelegation.delegate({ user, delegatee, governanceToken }); - -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1712,9 +1740,10 @@ const tx = powerDelegation.delegateByType({ delegationType, governanceToken, }); -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) +
@@ -1742,8 +1771,8 @@ const faucetService = new FaucetService(provider, faucetAddress); - @param `tokenSymbol` The symbol of the token you want to mint */ const tx = faucet.mint({ userAddress, reserve, tokenSymbol }); - -// Submit transaction as shown in Transaction Methods header ``` +Submit transaction as shown [here](#submitting-transactions) + From 11cdea92cde94761b7db0fe603045db19e6728f3 Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Wed, 26 Jan 2022 00:16:13 -0600 Subject: [PATCH 8/9] feat: add subgraph sections and general updates --- README.md | 398 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 316 insertions(+), 82 deletions(-) diff --git a/README.md b/README.md index 90171f29..d39f1a75 100644 --- a/README.md +++ b/README.md @@ -2,35 +2,42 @@

Aave Utilities

-Aave is a decentralized non-custodial liquidity market protocol where users can -participate as depositors or borrowers. The Aave Protocol is a set of open -source smart contracts which facilitate the supply and borrowing of user funds. -These contracts, and all user transactions/balances are stored on a public -ledger called a blockchain, making them accessible to anyone +The Aave Protocol is a decentralized non-custodial liquidity market protocol +where users can participate as depositors or borrowers. The protocol is a set of +open source smart contracts which facilitate the supply and borrowing of user +funds. These contracts, and all user transactions/balances are stored on a +public ledger called a blockchain, making them accessible to anyone -This Aave utilities packages give developers access to methods for formatting -contract data and executing transactions on the Aave protocol, and is compatible -with both Aave V2 and V3 +Aave Utilities is a JavaScript SDK for interacting with V2 and V3 of the Aave +Protocol, an upgrade to the existing [aave-js](https://github.com/aave/aave-js) +library -Aave Utilities is an upgrade to the existing -[aave-js](https://github.com/aave/aave-js) library, designed to be more modular, -efficient, and easier to use +The `@aave/math-utils` package contains methods for formatting raw +([ethers.js](#ethers.js)) or indexed ([subgraph](#subgraph), +[caching server](#caching-server)) contract data for usage on a frontend + +The `@aave/contract-helpers` package contains methods for generating trancations +based on method and parameter inputs. Can be used to read and write data on the +protocol contracts.
## Installation Aave utilities are available as npm packages, -[contract helpers](https://www.npmjs.com/package/@aave/contract-helpers), and +[contract helpers](https://www.npmjs.com/package/@aave/contract-helpers) and [math utils](https://www.npmjs.com/package/@aave/math-utils) +[ethers v5](https://docs.ethers.io/v5/) and [reflect-metadata](reflect metadata) +are peer dependencies of the contract-helpers package + ```sh // with npm -npm install --save ethers +npm install --save-dev ethers reflect-metadata npm install @aave/contract-helpers @aave/math-utils // with yarn -yarn add --dev ethers +yarn add --dev ethers reflect-metadata yarn add @aave/contract-helpers @aave/math-utils ``` @@ -40,7 +47,7 @@ yarn add @aave/contract-helpers @aave/math-utils 1. [Data Formatting Methods](#data-formatting-methods) - a. [Fetching Protocol Data](#fetching-protocol-data) - - [Smart Contract Calls](#smart-contract-calls) + - [ethers](#ethers.js) - [Subgraph](#subgraph) - [Caching Server](#caching-server) - b. [Format Reserve Data](#reserve-data) @@ -99,7 +106,7 @@ yarn add @aave/contract-helpers @aave/math-utils Users interact with the Aave protocol through a set of smart contracts. The `@aave/math-utils` package is a collection of methods to take raw input data from these contracts, and format to use on a frontend interface such as -[Aave UI](https://github.com/aave/aave-ui) or +[Aave Ui](https://github.com/aave/aave-ui) or [Aave info](https://github.com/sakulstra/info.aave) ## Fetching Protocol Data @@ -107,43 +114,17 @@ from these contracts, and format to use on a frontend interface such as Input data for these methods can be obtained in a variety of ways with some samples below: -- [Contract Queries](#contract-queries) +- [ethers](#ethers.js) - [Subgraph](#subgraph) - [Caching Server](#caching-server)
-### Contract Queries - -There are a variety of libraries which can be used to query the Aave protocol -smart contract. The basic process is: you provide the library with an rpc URL -and TypeChain bindings which will generate a typed sdk for interacting with -contract data - -The rpc endpoint is network-specific url will execute your requests to the -blockchain. The -[Aave UI networks config](https://github.com/aave/aave-ui/blob/master/src/ui-config/networks.ts) -gives a `publicJsonRPCUrl` for each supported network which can be used to make -requests **with** or **without** an API key. - -The following code snippets can be used to fetch data which can be passed -directly into [data formatting methods](#data-formatting-methods): - -- [ethers.js](#ethers.js) -- [web3.js](#web.js) -- [truffle](#truffle) - -
- ### ethers.js [ethers.js](https://docs.ethers.io/v5/) is a library for interacting with Ethereum and other EVM compatible blockchains. To install: -```sh -npm install --save ethers -``` - The first step to query contract data with ethers is to inialize a `provider`, there are a [variety](https://docs.ethers.io/v5/api/providers/) to choose from, all of them requiring the an rpcURL @@ -164,20 +145,22 @@ import { } from '@aave/contract-helpers'; // Sample RPC address for querying ETH mainnet -const provider = new ethers.provider.DefaultProvider( - 'https://cloudflare-eth.com', +const provider = new ethers.providers.JsonRpcProvider( + 'https://eth-mainnet.alchemyapi.io/v2/demo', ); -// This is the provider used in Aave UI, it checks the chainId locally to reduce RPC calls with frequent network switches, but requires that the rpc url and chainId to remain consistent with the request being sent from the wallet (i.e. - detecting the active chainId) -const providerAlt = new ethers.providers.StaticJsonRpcProvider( - 'https://cloudflare-eth.com', +// This is the provider used in Aave UI, it checks the chainId locally to reduce RPC calls with frequent network switches, but requires that the rpc url and chainId to remain consistent with the request being sent from the wallet (i.e. actively detecting the active chainId) +const provider = new ethers.providers.StaticJsonRpcProvider( + 'https://eth-mainnet.alchemyapi.io/v2/demo', ChainId.mainnet, ); -// Aave protocol contract addresses, will be different for each market and can be found at https://docs.aave.com/developers/deployed-contracts/deployed-contracts or https://github.com/aave/aave-ui/blob/master/src/ui-config/markets/index.ts -const uiPoolDataProviderAddress = ''; -const uiIncentiveDataProviderAddress = ''; -const lendingPoolAddressProvider = ''; +// Aave protocol contract addresses, will be different for each market and can be found at https://docs.aave.com/developers/deployed-contracts/deployed-contracts +// For V3 Testnet Release, contract addresses can be found here https://github.com/aave/aave-ui/blob/feat/arbitrum-clean/src/ui-config/markets/index.ts +const uiPoolDataProviderAddress = '0xa2DC1422E0cE89E1074A6cd7e2481e8e9c4415A6'; +const uiIncentiveDataProviderAddress = + '0xD01ab9a6577E1D84F142e44D49380e23A340387d'; +const lendingPoolAddressProvider = '0xB53C1a33016B2DC2fF3653530bfF1848a515c8c5'; // User address to fetch data for const currentAccount = ''; @@ -194,6 +177,8 @@ const incentiveDataProviderContract = new UiIncentiveDataProvider({ provider, }); +// Note, contract calls should be performed in an async block, and updated on interval or on network/market change + // Object containing array of pool reserves and market base currency data // { reservesArray, baseCurrencyData } const reserves = await poolDataProviderContract.getReservesHumanized({ @@ -225,14 +210,6 @@ const userIncentives =
-### web.js - -
- -### truffle - -
- ### Subgraph A subgraph indexes events emitted from a smart contract and exposes a graphql @@ -247,24 +224,280 @@ resources on querying subgraph from a frontend application. Here are queries for fetching the data fields required for [data formatting methods](#data-formatting-methods). The formatting methods are the same for V2 and V3, but the queries required to fetch the input data are -different. The result will need to be formatted +different. Queries will depend on two parameters: + +- `pool` : lendingPoolAddressProvider address for the market you are querying + data for +- `user` : user to fetch account data for
V2 +
+ Reserves + +```graphql +{ + reserves( + where: { pool: "insert_lowercase_lending_pool_address_provider_here" } + ) { + id + symbol + name + decimals + underlyingAsset + usageAsCollateralEnabled + reserveFactor + baseLTVasCollateral + averageStableRate + stableDebtLastUpdateTimestamp + liquidityIndex + reserveLiquidationThreshold + reserveLiquidationBonus + variableBorrowIndex + variableBorrowRate + liquidityRate + totalPrincipalStableDebt + totalScaledVariableDebt + lastUpdateTimestamp + availableLiquidity + stableBorrowRate + totalLiquidity + price { + priceInEth + } + } +} +``` + +Then formatted to match expected input schema with: + ```ts +const reserves = queryResult.reserves.map(reserve => { + return { + ...reserve, + priceInMarketReferenceCurrency: reserve.price.priceInEth, + eModeCategoryId: 0, + borrowCap: '', + supplyCap: '', + debtCeiling: '', + debtCeilingDecimals: 0, + isolationModeTotalDebt: '', + eModeLtv: 0, + eModeLiquidationThreshold: 0, + eModeLiquidationBonus: 0, + }; +}); +``` + +
+ +
+ User Reserves +```graphql +{ + userReserves(where: {pool: "insert_lowercase_lending_pool_address_provider_here", user: "insert_lowercase_user_address_here"}) { + reserve{ + underlyingAsset + } + scaledATokenBalance + usageAsCollateralEnabledOnUser + stableBorrowRate + scaledVariableDebt + principalStableDebt + stableBorrowLastUpdateTimestamp + } + } +} +``` + +Then formatted to match expected input schema with: + +```ts +const userReserves = queryResults.userReserves.map(userReserve => { + return { + ...userReserve, + underlyingAsset: userReserve.reserve.underlyingAsset, + }; +}); ``` +The `userEmodeCategoryId` parameter will always be 0 for V2 markets. + +
+ +
+ Base Currency Data + +```graphql +{ + priceOracles { + usdPriceEth + } +} +``` + +For ETH-based markets (all V2 markets except Avalanche): + +- `marketReferencePriceInUsd` = 1 / (queryResult.priceOracles[0].usdPriceEth / + (10 \*\* 18)) + +- `marketReferenceCurrencyDecimals` = 18 + +For USD-based markets (Avalanche and all v3 markets): + +- `marketReferencePriceInUsd` = 1 / (queryResult.priceOracles[0].usdPriceEth / + (10 \*\* 8)) + +- `marketReferenceCurrencyDecimals` = 8 + +
+ +
+ Incentives + +Samples for incentives data coming soon. Uses `incentivesControlllers` field and +maps incentives to reserves and userReserves. + +
+
V3 +
+ Reserves + +```graphql +{ + reserves( + where: { pool: "insert_lowercase_lending_pool_address_provider_here" } + ) { + id + symbol + name + decimals + underlyingAsset + usageAsCollateralEnabled + reserveFactor + baseLTVasCollateral + averageStableRate + stableDebtLastUpdateTimestamp + liquidityIndex + reserveLiquidationThreshold + reserveLiquidationBonus + variableBorrowIndex + variableBorrowRate + liquidityRate + totalPrincipalStableDebt + totalScaledVariableDebt + lastUpdateTimestamp + availableLiquidity + stableBorrowRate + totalLiquidity + price { + priceInEth + } + eModeCategoryId + borrowCap + supplyCap + debtCeiling + debtCeilingDecimals + isolationModeTotalDebt + eModeLtv + eModeLiquidationThreshold + eModeLiquidationBonus + } +} +``` + +Then formatted to match expected input schema with: + ```ts +const reserves = queryResults.map(queryResult => { + return { + ...queryResult, + priceInMarketReferenceCurrency: queryResult.price.priceInEth, + }; +}); +``` + +
+ +
+ User Reserves + +```graphql +{ + userReserves( + where: { + pool: "insert_lowercase_lending_pool_address_provider_here" + user: "insert_lowercase_user_address_here" + } + ) { + reserve { + underlyingAsset + } + scaledATokenBalance + usageAsCollateralEnabledOnUser + stableBorrowRate + scaledVariableDebt + principalStableDebt + stableBorrowLastUpdateTimestamp + user { + eModeCategoryId { + id + } + } + } +} +``` + +Then formatted to match expected input schema with: + +```ts +const userReserves = queryResults.map(queryResult => { + return { + ...queryResult, + underlyingAsset: queryResult.reserve.underlyingAsset, + }; +}); +``` + +The field `queryResults[0].user.eModeCategoryId.id` is the active eModeCategory +and will input to the user formatters separately. + +
+ +
+ Base Currency Data +```graphql +{ + priceOracles { + usdPriceEth + baseCurrencyUnit + } +} ``` +- `marketReferencePriceInUsd` = 1 / (queryResult.priceOracles[0].usdPriceEth / + (10 \*\* 8)) +- `marketReferenceCurrencyDecimals` = + queryResult.priceOracles[0].baseCurrencyUnit.toString().length + +
+ +
+ Incentives + +Samples for incentives data coming soon. Uses `incentivesControlllers` field and +maps incentives to reserves and userReserves. + +
+

@@ -314,13 +547,14 @@ each reserve in an Aave market ```ts import { formatReserves } from '@aave/math-utils'; +import dayjs from 'dayjs'; // reserves input from Fetching Protocol Data section const reservesArray = reserves.reservesData; const baseCurrencyData = reserves.baseCurrencyData; -const currentTimestamp = Math.round(new Date().getTime() / 1000); +const currentTimestamp = dayjs().unix(); /* - @param `reserves` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` @@ -352,13 +586,14 @@ incentives for each reserve in an Aave market ```ts import { formatReservesAndIncentives } from '@aave/math-utils'; +import dayjs from 'dayjs'; // 'reserves' and 'reserveIncentives' inputs from Fetching Protocol Data section const reservesArray = reserves.reservesData; const baseCurrencyData = reserves.baseCurrencyData; -const currentTimestamp = Math.round(new Date().getTime() / 1000); +const currentTimestamp = dayjs().unix(); /* - @param `reserves` Input from [Fetching Protocol Data](#fetching-protocol-data), `reserves.reservesArray` @@ -398,6 +633,7 @@ factor, and available borrowing power ```ts import { formatUserSummary } from '@aave/math-utils'; +import dayjs from 'dayjs'; // 'reserves' and 'userReserves' inputs from Fetching Protocol Data section @@ -405,25 +641,15 @@ const reservesArray = reserves.reservesData; const baseCurrencyData = reserves.baseCurrencyData; const userReservesArray = userReserves.userReserves; -const currentTimestamp = Math.round(new Date().getTime() / 1000); +const currentTimestamp = dayjs().unix(); -// Combine reserve data with user data -const userReservesFormatted: UserReserveData[] = []; -if (userReservesArray && reservesArray.length) { - userReservesArray.forEach(rawUserReserve => { - const reserve = reservesArray.find( - r => - r.underlyingAsset.toLowerCase() === - rawUserReserve.underlyingAsset.toLowerCase(), - ); - if (reserve) { - userReservesFormatted.push({ - ...rawUserReserve, - reserve, - }); - } - }); -} +const formattedPoolReserves = formatReserves({ + reserves: reservesArray, + currentTimestamp, + marketReferenceCurrencyDecimals: + baseCurrencyData.marketReferenceCurrencyDecimals, + marketReferencePriceInUsd: baseCurrencyData.marketReferenceCurrencyPriceInUsd, +}); /* - @param `currentTimestamp` Current UNIX timestamp in seconds, Math.floor(Date.now() / 1000) @@ -456,13 +682,16 @@ factor, available borrowing power, and dictionary of claimable incentives Sample Code ```ts +import { formatUserSummaryAndIncentives } from '@aave/math-utils'; +import dayjs from 'dayjs'; + // 'reserves', 'userReserves', 'reserveIncentives', and 'userIncentives' inputs from Fetching Protocol Data section const reservesArray = reserves.reservesData; const baseCurrencyData = reserves.baseCurrencyData; const userReservesArray = userReserves.userReserves; -const currentTimestamp = Math.round(new Date().getTime() / 1000); +const currentTimestamp = dayjs().unix(); // Combine reserve data with user data const userReservesFormatted: UserReserveData[] = []; @@ -1608,6 +1837,9 @@ Submit transaction as shown [here](#submitting-transactions) Queue the proposal (If Proposal Succeeded) +
+ Sample Code + ```ts import { AaveGovernanceService } from '@aave/contract-helpers'; @@ -1624,6 +1856,8 @@ const governanceService = new AaveGovernanceService(rpcProvider, { const tx = governanceService.queue({ user, proposalId }); ``` +
+ Submit transaction as shown [here](#submitting-transactions) From c08903aebafb669373e263aa51afee9ab28a5b9c Mon Sep 17 00:00:00 2001 From: Andrew Schmidt Date: Wed, 26 Jan 2022 00:27:07 -0600 Subject: [PATCH 9/9] fix: small changes --- README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d39f1a75..98ca09a9 100644 --- a/README.md +++ b/README.md @@ -206,6 +206,10 @@ const userIncentives = }); ``` +These four variables are passed as parameters into the [reserve](#reserve-data) +and [user](#user-data) formatters to compute all of the fields needed for a +frontend interface. +
@@ -1856,12 +1860,12 @@ const governanceService = new AaveGovernanceService(rpcProvider, { const tx = governanceService.queue({ user, proposalId }); ``` - - Submit transaction as shown [here](#submitting-transactions) + +
### execute