aave / aave-utilities Goto Github PK
View Code? Open in Web Editor NEWLicense: MIT License
License: MIT License
So when we are dealing with something that if something goes wrong with the value or the value wrong someone could execute something very bad proper class types normally come in nice. What I mean by this is let's take userId as an example you probably wouldn't do it for this but just to explain what I mean and assume its a guid, instead of string it be a UserId
class aka:
export function formatUserSummaryData(
poolReservesData: ReserveData[],
rawUserReserves: UserReserveData[],
userId: string,
usdPriceEth: BigNumberValue,
currentTimestamp: number
turns into
export function formatUserSummaryData(
poolReservesData: ReserveData[],
rawUserReserves: UserReserveData[],
userId: UserId,
usdPriceEth: BigNumberValue,
currentTimestamp: number
Now on this class, it validates and throws runtime errors if it doesn't match the time on new User(xxxxx)
stopping anything bad from happening. You could write it similar to this:
export default class UserId extends BaseType<Guid, string, string> {
private _value: string | undefined;
constructor(value: string) {
super(new.target.name, value);
}
public equals(other: Guid): boolean {
return other.value === this.value;
}
protected validate(): void {
if (typeof this._value !== 'string' || !Utils.isGuid(this._value)) {
throw Errors.runtimeErrorWithLogger(
this._log,
'String supplied is not a guid string',
this._value,
);
}
}
protected setValue(value: string): void {
if (typeof value === 'string') {
this._value = value;
}
}
public get value(): string {
if (!this._value) {
throw this.valueNotSetError();
}
return this._value;
}
}
export default abstract class BaseType<TClass, TValue, TSetValue> {
protected _log: Logger;
constructor(className: string, value: TSetValue) {
this._log = new Logger(className);
// set the value
this.setValue(value);
// force the validation to always fire straight away on creation of any classes
// which extend the Base
this.validate();
}
/**
* Gets the value
*/
public abstract get value(): TValue;
/**
* Validate the class
*/
protected abstract validate(): void;
/**
* Sets the value
*/
protected abstract setValue(value: TSetValue): void;
/**
* Is equal to
* @param other The other class
*/
public abstract equals(other: TClass): boolean;
/**
* Value not set error
*/
protected valueNotSetError(): Error {
return Errors.runtimeErrorWithLogger(this._log, 'Value set is undefined');
}
}
Now as you use TS you start forgetting to check certain details and this brings in this approach.
Add all the getter methods of the new UiIncentivesProvider to the data module. Should have all the necessary methods so the client can continue to have the same functionality
Document return types for data formatting methods
Remove references to "raw" in file names.
Comment everything.
Document the main entry point (currently user/index.ts) in README as well.
1.) Break logic in generate-raw-summary and generate-raw-reserve down further.
2.) Remove any modifications to ReserveData in format-user-reserve, should all be handled in previous steps
3.) Unit test
Obviously, TheGraph is good to do some queries but on some cases we do not need to use the graph. Even more nothing stopping us create solidity helper contracts to avoid fees altogether this would improve:
A lot of cases we don't even need a helper sol we can use multicall and the standard onchain contract to lookup the data.
Review why the usd decimals are 10, when the usd price we get from chainlink is in 8 decimals.
Its possible that its because it was tied with the 18 decimals of eth price, but as we move away from eth base price we should remember to also change this
Add functions to src/formatters/incentive:
Input types based on https://github.com/aave/protocol-v2/blob/c786b246ccdb58537b0f8b61dbb23a6b409baa12/contracts/misc/UiIncentiveDataProvider.sol
Currently there's no easy way to figure out the aave addresses (aka there's no package one can import to get the currently up to date addresses). Also there's no easy way to get notified in case an address was updated.
What currently get's closest to this is:
https://github.com/aave/aave-addresses with jsons per network https://aave.github.io/aave-addresses/kovan.json
This is lacking helper contracts though as they are not registered at the protocol.
For helper contracts I think it would be reasonable to have a static addresses = {[Network]: string}
on the service so that people can simply access the address.
We could also have a @aave/constants
package or similar containing the addresses. This package could contain all the "generatable addresses" and all the helper contract addresses.
Create new data provider for incentives to pull data from UiIncentiveDataProvider contract.
Use incentive helpers to calculate and display total claimable rewards.
Add a guide to the README explaining the process used on the Aave frontend to fetch and format pool data using the UiPoolDataProvider contract and formatReserves / formatUserSummaryData helper functions.
Add UiPoolDataProvider contract code and addresses to the GitBook docs.
Port and adapt the tx-builder initializations to be used with different importable modules:
We tend to do separate JSONRPC async calls even if we are calling the same contract for example
This will call the same contract twice once to get the decimals and another time to get the allowance. We can bulk these together into 1 JSONRPC call meaning we doing less calls and quicker responses.
metric shows that a JSONRPC request most the times the network coming back eats up most the response time
say you got 3 jsonrpc calls they will probs take 200MS each = 600MS (as it awaits for response)
if you batch this in 1 single JSONRPC call the result tends to be 200MS or close to = x3 improvement in speed.
We can batch together more then just a single contract as well say a method calls 4-5 different contracts we can use this to batch it in 1 JSONRPC again. This can really improve speed and bills from the node provider.
Open source lib which I support which we could use for this -
https://github.com/joshstevens19/ethereum-multicall
Create the data module of tx-builder and add the different data getters for UiPoolDataProvider. (Keep in mind that it should use the new version of the provider, the one that has not incentives data on the reserves)
Remove the return of the reserve incentives from the UiPoolDataProvider.
Use current deployed version as base: https://github.com/aave/protocol-v2/blob/feat/split-ui-dataprovider-logic/contracts/misc/UiPoolDataProvider.sol
move from 139 - 160 (reserve incentives)
move from 187 - 200 (user reserve incentives)
Also move emissionEndTimestamp (given by incentivesController)
Also move userUnclaimedRewards (incentive rewards unclaimed by the user)
We need to Add also an extra check to instead of passing or hardcoding the incentives controller, we should get it from the a/s/v tokens (as they are initialized with it) this will give us also the possibility to operate with incentive controller by token instead of by network. Take into account that having incentivesController by token we will also need to get emissionEndTimestamp by token (not sure if this will have reaple effect. I think it shouldn't as if multiple tokens have same incentivesController the emissionEndTimestamp will be the same)
userUnclaimedRewards will also be affected by the incentivesController by token. If we have different IncentivesControllers then we provably will need to add all the userUnclaimedRewards but if they are the same then we shouldn't as userUnclaimedRewards accounts for all the unclaimedRewards of the different token incentives. Maybe we could calculate teh unclaimed rewards by getting for every asset the method getUserAssetData, and reproducing smart contract calls in the lib, this way we could query for every token without the need to add extra logic in the contract. (So yeah, take a deeper look at that part)
Update the caching-service with the new UiPoolDataProvider (without the reserve incentives)
Add the new IncentivesProvider helper contract to the caching-service so as to query with different frequency (15 - 20 secs) than the reserves quering.
The data provided by this should be usable with the new aave-js lib
In aave-js we got raymath methods based on BigNumbers
https://github.com/aave/aave-js/blob/master/src/helpers/ray-math.ts
We might consider re-implementing them based on ethers BigNumber, which is what most dapps use by default.
This will result in reduced bundle size for people relying on that library & usually better performance as bignumber.js is quite expensive.
Background: They used the wrong debt token which has the incentives controller as private. This means they cannot get the incentives controller from the token and therefore cannot display the correct apr.
Hardcode Fei incentives so it is as if it was native incentive, so it can show apr % and can be claimed directly from app.aave.com
This is needed because the FEI debtToken that is incentiviced is not from the latest version of tokens, so we can not get the incentive information automatically from the UiIncentivesProvider contract
As you can see in our ci workflow we're having multiple issues with lerna right now.
lerna/lerna#2788
lerna/lerna#1893
Lerna seems to be no longer properly maintained: lerna/lerna#1893
Might make sense to put some effort into fixing them/maintaining a fork as prs at lerna seem to be no longer to be accepted.
Currently the data functions require an excessive number of inputs, this should be re-designed to be easier to integrate.
Suggestion:
An aaveDataProvider object that can be initialized with a network and provider, and supports the following functions
userSummary(userAddress, marketAddress?, assetAddress?)
reserveSummary(marketAddress?, assetAddress?)
where marketAddress = lendingPoolAddressProvider for the market, assetAddress = underlyingAssetAddress, and market/asset default to all if not specified.
Add faucets to helper contracts
Namespaces = beautiful codebase to work with mainly because its easy to get to certain things. for example on v1 tx builder you have a file called computations-and-formatting.ts
and this has many functions in it. If we can expose a clean interface to interact with it this means the learning curve for the user is a lot less.
stuff like
aave.v1.calculate.compoundedInterest
aave.v1.calculate.healthFactorFromBalances
aave.v1.calculate.availableBorrowsETH
aave.v1.format.reserves
aave.v1.format.userSummaryData
etc etc! you want to do this in a partial import way so would be more like:
import { calculate as v1Calculate, format as v1Format } from 'aavejs/v1'
v1Calculate.compoundedInterest
v1Calculate.healthFactorFromBalances
v1Calculate.availableBorrowsETH
v1Format.reserves
v1Format.userSummaryData
The aim here is to make your tech easy for everyone to understand, starting with the interface just like a REST API make it human-readable and its a great start
Change lendingPool name to lendingPoolAddressProvider
Change to typechain
These are all generated files aka they should not be touched manually they are autogenerated we should move them out of touch so they don't randomly get changed. Going forward we should sync with the contracts and make on push generate these typings and upload them to the shared package.
Add a new helper contract for v3 Pool.sol contract.
Should have old methods (same functionality) + new ones (eMode, isolation, etc)
We need to update the UiPoolDataProvider so it takes into account the base currency of the market. this is the version we should branch of: https://github.com/aave/protocol-v2/tree/feat/split-ui-dataprovider-logic
To do this we need to get the information of the AaveOracle.
0 - get AaveOracle from PoolAddressProvider
1 - get Base currency information from AaveOracle:
Background: We are using subgraphs for different things. We use it for different versions. Some issues
Achieve: How can we replace this service?
Alternatives: Bitquery?
TypeChain
is awesome but at the end of the day, it adds bundle size to the output. Every TypeChain
factory IS a class and you have to call it like this.contractFactory.connect
< this ADDS bundle size to the output. If you look what is in some of these factories it has LONG abi strings etc which can eat up bundle size for sure! Just look at tx-builder
> contract-types
that's 428KB of stuff that could be added to the output of the bundle.
I promote we use https://github.com/joshstevens19/ethereum-abi-types-generator < was built for this exact reason you just use native ethers interface and everything in the generated types are interfaces meaning once compiled no bundle size is added to the output (as interfaces are not real). It also does other things typechain does not > https://github.com/joshstevens19/ethereum-abi-types-generator#ethereum-abi-types-generator-vs-typechain
On top of this I see in the project you have got the return types of the contracts tx-builder > types
this will all be redundant with this package as it exposes them all for you without you having to recreate it.
not the end of the world but if our aim is bundle size aka smallest package going then this could be a good place to start.
In the current version of @aave/protocol-js
we have a lot of non required timestamps where we then default to Date.now()
or similar.
This caused a few issues in the past with wrong system clocks and shit like that. While making these field required won't necessarily solve these issues it will make debugging them easier.
Imo low level utility library should be as explicit as possible - if a method needs the currentTimestamp to perform it's math it should be a required field, not optional.
This was previously discussed and decided - if you disagree though, feel free to comment.
Background:
The tx builder in AAVEJS. A private package that we open sourced. Migrated https://github.com/aave/aave-js/tree/master/src/tx-builder into Aave JS.
If you want to interact with the protocol there are specific requirements. A lot of these methods have many parameters. Ie specify which pool, credit delegation, borrow, flashloan, etc.
The tx builder allows you to expose an easy to use and type interface to interact with the Aave protocol.
Problem: This was built for Aave v1 and for graph data. Most times you get data from RPC and not the graph data. Currently we are transforming the slim RPC data back to nested graph structure so can use older helper functions. They will split the up the configuration file https://github.com/aave/aave-js/blob/master/src/tx-builder/config/defaultConfig.ts#L3 . Plan is to expose single service for lending pool, incentives, governance, staking, swapping.
formatUserSummary doesn't return availableBorrowsUSD
but all other usd values
0.15
Method should return either all or no usd values, but not mixed content.
In ethers everytime you do a JSONRPC call with JsonRpcProvider
it will call eth_chainId
before it does the request meaning it slows down the response from you main query. StaticJsonRpcProvider
does not do this meaning less JSONRPC call with faster responses.
Currently aave-js is a single pakage shipping everything included although you might never need it.
Therefore it would be great if our new package structure would allow publishing @aave/tx-builder
and perhaps more from a single repo @aave/calculation-utils
.
In the past i've been using lerna for these kind of things, but there might be newer/cooler stuff with native typescript support.
Example of a lerna monrorepo: visx
Currently formatReserves
does a lot besides formatting the reserve. Reward incentive calculation should not be part of it, because:
a) most reserves don't have rewards
b) you might not be interested in rewards
c) in the future we might have multiple rewards per reserve
Therefore my suggestion would be to not do it at all in formatReserves
and move the responsibility to userland via calculateAPYs
or similar. Once we know exactly how this will work in the future we might add an additional helper method to calculate multiple incentives at once, but that's not needed yet.
formatReserve
formatUserReserve
Currently each network only has one associated reward asset and IncentivesController in the aave-ui. That#s a oversimplification that was true, but is no longer true.
In theory every subtoken (a/s/v) can have it's own incentiveController and we should support that.
Currently we have most configs in packag.json - we had to learn that#s confusing is people didn't seem to understand where lint & jest rules came from.
Let's move it to a config file or folder
Currently we use both USD and ETH in he library.
As the baseCurrency is variable though we shouldn't be opinionated on the currency imo (especially now as it might change).
priceInEth
will essentially be tokenPriceInReferenceCurrency
(perhaps we find a better name, but that's what it is, might be eth/usd/avax, we don't know we don't care)usdPriceEth
we have a usdPriceReferenceCurrency
(for usd feeds this will be one)referencePriceDecimals
field which oppose to our current static 18 decimals needs to be used when doing stuff with the former usdPriceEth
Feel free to suggest better parameter naming
For reliability and avoiding paid queries on The Graph mainnet, a library (or at least a mode) which fetches data from contract calls would be preferred
UiPoolDataProvider (https://etherscan.io/address/0x48d164699f0C95AA0dC4097D74413EA216564F97) can be used for fetching a summary of both reserve and user data
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.