From 9945280cdcdff57916c74448bbf7a91651439656 Mon Sep 17 00:00:00 2001 From: rossgalloway <58150151+rossgalloway@users.noreply.github.com> Date: Tue, 21 Jan 2025 09:59:16 -0500 Subject: [PATCH] Feat: wallet integration guide (#499) * feat: wallet and portfolio tracker integration doc * fix: grammar * fix: update kong APY types. * fix: missing vaults and incorrect links * fix: add ens * fix: add info on APY/APR --- docs/contributing/contribute.md | 6 +- docs/developers/addresses/v3-contracts.md | 2 +- docs/developers/data-services/yearn-data.md | 21 +- docs/developers/v1/interfaces.md | 158 +---------- docs/developers/wallet-integration.md | 300 ++++++++++++++++++++ scripts/fetchedAddressData.json | 3 +- sidebars/sidebarsDeveloperDocs.js | 31 +- src/ethereum/constants.ts | 3 + 8 files changed, 342 insertions(+), 182 deletions(-) create mode 100644 docs/developers/wallet-integration.md diff --git a/docs/contributing/contribute.md b/docs/contributing/contribute.md index 712af8167..7fd863cee 100644 --- a/docs/contributing/contribute.md +++ b/docs/contributing/contribute.md @@ -38,7 +38,7 @@ You can see our progress on the [Github Project Board](https://github.com/orgs/y We use a combination of HackMD, Docusaurus, and Github for our [Documentation](https://docs.yearn.fi/) and we use [DrawIO](https://draw.io) with Google Drive for our diagrams & schemas. If you are a grammar stickler, you can see our [Reviewer Guide](https://hackmd.io/juTKNn3xTpKJgFDo2AglLw). -Last but not least, join the #documentation channel in [Discord](https://discord.gg/freT6YRNSX) and introduce yourself. +Last but not least, join the #documentation channel in [Discord](https://discord.gg/yearn) and introduce yourself. If this sounds confusing, please let us know what we can clear up. In the meantime: You can begin contributing to our HackMD docs immediately via the Github issues — we'll guide you through the rest. @@ -48,7 +48,7 @@ If this sounds confusing, please let us know what we can clear up. In the meanti If you're a developer, we need your help! Before you begin: Familiarize yourself with Yearn, its products, and its infrastructure by reading our [Documentation](https://docs.yearn.fi/). -You can see our progress on our [Github Project Board](https://contribute.yearn.farm/good-first-issue.html), and you can immediately begin contributing where you see fit. We recommend checking out issues tagged as `help wanted` and recommend sticking to the respective repository's coding guidelines (linting, formatting, PRs, etc). It's that simple 🙂. You can also join us on the #dev channel in [Discord](https://discord.gg/w89vVxeV9h). +You can see our progress on our [Github Project Board](https://contribute.yearn.farm/good-first-issue.html), and you can immediately begin contributing where you see fit. We recommend checking out issues tagged as `help wanted` and recommend sticking to the respective repository's coding guidelines (linting, formatting, PRs, etc). It's that simple 🙂. You can also join us on the #dev channel in [Discord](https://discord.gg/yearn). If you are interested in working on a specific project, check out the list of Yearn products in the [General Resources](#general-resources) section below or check out our list of repos [here](https://github.com/orgs/yearn/repositories). @@ -60,7 +60,7 @@ If you want to integrate with Yearn, please visit our [Integration Guide](https: #### Designers -We invite designers, animators, artists, and more to share your skills with the Yearn ecosystem! If you're interested in creating graphics that describe Yearn's systems, creating video explainers, fixing Yearn's UI/UX, or any other combination of things — hop into the #ui-ux channel or #media-resources channels in [Discord](https://discord.gg/H8AVhpz63R). +We invite designers, animators, artists, and more to share your skills with the Yearn ecosystem! If you're interested in creating graphics that describe Yearn's systems, creating video explainers, fixing Yearn's UI/UX, or any other combination of things — hop into the #ui-ux channel or #media-resources channels in [Discord](https://discord.gg/yearn). #### Creating Strategies diff --git a/docs/developers/addresses/v3-contracts.md b/docs/developers/addresses/v3-contracts.md index c24931a88..b80715980 100644 --- a/docs/developers/addresses/v3-contracts.md +++ b/docs/developers/addresses/v3-contracts.md @@ -75,5 +75,5 @@ To find individual vaults, use the V3 Registry below or refer to https://yearn.f | ---------------------- | ---------------------- | | **Role Manager**
role-manager.v3.ychad.eth | | | **Current V3 Registry**
registry.v3.ychad.eth | | -| **Legacy V3 Registry**
| [0xff31A1B020c868F6eA3f61Eb953344920EeCA3af](https://etherscan.io/address/0xff31A1B020c868F6eA3f61Eb953344920EeCA3af) | +| **Legacy V3 Registry**
| | | **Accountant**
accountant.v3.ychad.eth | | diff --git a/docs/developers/data-services/yearn-data.md b/docs/developers/data-services/yearn-data.md index 93a8cbd1a..72c801b6b 100644 --- a/docs/developers/data-services/yearn-data.md +++ b/docs/developers/data-services/yearn-data.md @@ -11,11 +11,30 @@ yDaemon is a RESTful API that hydrates subgraph responses with more data, like A - **Docs:** https://ydaemon.yearn.farm/docs/intro - **Guide:** https://medium.com/iearn/ydaemon-one-api-to-unify-all-yearn-data-4fc74dc9a33b +## Kong + +[Kong](https://kong.yearn.farm/) is an integrated set of services and tools that make it easy to index EVM logs and state, enrich your data with custom hooks, query your data over graphql. Kong is designed to be cheap, reliable, easy to maintain, and simplify the process of updating your index. + +Kong's Yearn index covers the v3 and v2 vault ecosystems: + +- Regular contract snapshots of each registry, vault, strategy, trade handler, accountant, and debt allocator. +- Full event history for each of the above (*with limited history on transfers, deposits, withdraws, and approves). +- Snapshot hooks for computing vault-strategies relationships, debts, fees, and rewards. +- Snapshot hooks for integrating off-chain risk and meta data. +- Event hooks for tracking new vaults and strategies, computing spot harvest APRs, and pricing transfers. +- Timeseries hooks for computing APY and TVL. + +Kong can be run locally or a hosted version run by Yearn can be queried with the public endpoint. + +- **Live API:** https://kong.yearn.farm/api/gql +- **Source:** https://github.com/yearn/kong +- **Docs:** Under Construction 🚧 + ## Subgraph :::info -Currently only subgraphs for V2 vaults are available and some subgraphs have not been migrated to the new service. +Currently only subgraphs for V2 vaults are available and some subgraphs have not been migrated to the new service. We recommend using Kong or yDaemon for your data needs. ::: diff --git a/docs/developers/v1/interfaces.md b/docs/developers/v1/interfaces.md index bdbc9b4ad..5efb46662 100644 --- a/docs/developers/v1/interfaces.md +++ b/docs/developers/v1/interfaces.md @@ -12,16 +12,10 @@ Source code: [yearn-protocol/develop/interfaces/yearn/IStrategy.sol](https://git Returns the address of the unwrapped token that the Strategy takes as deposit. - - ```javascript function want() external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | -------------------------------------------------- | | Output | 0 | address | Address of the token the Strategy takes as deposit | @@ -30,16 +24,10 @@ function want() external view returns (address); Deposits token (same as `want()` returns) into a smart contact specified by the Strategy. - - ```javascript function deposit() external; ``` - - ### function `withdraw(address)` Dust collecting function to create additional rewards out of tokens that were incorrectly sent to the Strategy. @@ -48,16 +36,10 @@ Takes an ERC20 token address and should send the full amount of any such tokens This function should have access control enforcing the Controller only to be its allowed caller, and checks in place to ensure that the token types to withdraw are not those used by the Strategy. - - ```javascript function withdraw(address) external; ``` - - | | | type | desc | | ----- | --- | ------- | -------------------------- | | Input | 0 | address | ERC-20 token to be drained | @@ -66,16 +48,10 @@ function withdraw(address) external; Partially withdraws funds (denominated in `want()` token) from the Strategy, and should always only be sending these to the Vault. In case the Strategy implements `harvest()`, a withdrawal fee may be applied. This function should have access control enforcing the Controller only to be its allowed caller. - - ```javascript function withdraw(uint256) external; ``` - - | | | type | desc | | ----- | --- | ---- | ---------------------- | | Input | 0 | uint | Amount to be withdrawn | @@ -84,16 +60,10 @@ function withdraw(uint256) external; Used to obtain the remaining amount that can be borrowed from the lending platform. Relevant when the Strategy implements a lending platform, such as Aave. - - ```javascript function skim() external; ``` - - ### function `withdrawAll()` Withdraws the entire amount of `want()` tokens available, and should always only be sending these to the Vault. This function should have access control enforcing the Controller only to be its allowed caller. Typically used when migrating strategies. @@ -104,16 +74,10 @@ If the Strategy implements liquidity pools or lending platforms, then withdrawal Returns a `uint256` of the total amount withdrawn. - - ```javascript function withdrawAll() external returns (uint256); ``` - - | | | type | desc | | ------ | --- | ------- | -------------------- | | Output | 0 | uint256 | The amount withdrawn | @@ -122,16 +86,10 @@ function withdrawAll() external returns (uint256); Returns the Strategy's current `want()` token balance. - - ```javascript function balanceOf() external view returns (uint256); ``` - - | | | type | desc | | ------ | --- | ------- | --------------------------------- | | Output | 0 | uint256 | Strategy's `want()` token balance | @@ -144,16 +102,10 @@ Source code: [yearn-protocol/develop/interfaces/yearn/IVault.sol](https://github Returns the unwrapped native token address that the Vault takes as deposit. - - ```javascript function token() external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | -------------------------------------- | | Output | 0 | address | Vault’s unwrapped native token address | @@ -162,17 +114,11 @@ function token() external view returns (address); Returns the native underlying token address in Delegated Vaults. For example, in case of aLINK delegated vault, `underlying()` returns the address of the LINK token. - - ```javascript // This is only implemented in Delegated Vaults. function underlying() external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | ------------------------------------------------- | | Output | 0 | address | Delegated Vault’s underlying native token address | @@ -181,16 +127,10 @@ function underlying() external view returns (address); Returns the vault’s wrapped token name as a string, e.g. “yearn Dai Stablecoin". - - ```javascript function name() external view returns (string memory); ``` - - | | | type | desc | | ------ | --- | ------ | -------------------------- | | Output | 0 | string | Vault’s wrapped token name | @@ -199,16 +139,10 @@ function name() external view returns (string memory); Returns the vault’s wrapped token symbol as a string, e.g. “yDai”. - - ```javascript function symbol() external view returns (string memory); ``` - - | | | type | desc | | ------ | --- | ------ | ---------------------------- | | Output | 0 | string | Vault’s wrapped token symbol | @@ -217,16 +151,10 @@ function symbol() external view returns (string memory); Returns the amount of decimals for this vault’s wrapped token as a `uint8`. - - ```javascript function decimals() external view returns (uint8); ``` - - | | | type | desc | | ------ | --- | ----- | -------------------------------------------- | | Output | 0 | uint8 | No of decimals of the vault's wrapped token. | @@ -235,16 +163,10 @@ function decimals() external view returns (uint8); Returns the address of the Vault's Controller. - - ```javascript function controller() external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | --------------------------- | | Output | 0 | address | Vault’s Controller contract | @@ -253,16 +175,10 @@ function controller() external view returns (address); Returns the address of the Vault’s governance contract. - - ```javascript function governance() external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | --------------------------- | | Output | 0 | address | Vault’s Governance contract | @@ -274,21 +190,15 @@ Returns the price of the Vault’s wrapped token, denominated in the unwrapped n The calculation is: $$ -\{nativeTokenBalance \over yTokenTotalSupply} +\frac{nativeTokenBalance}{yTokenTotalSupply} $$ Where `nativeTokenBalance` is the current balance of native token \(e.g. DAI\) in the Vault, Controller and Strategy contracts. And `yTokenTotalSupply` is the total supply of the Vault's wrapped Token \(e.g. yDAI\). - - ```javascript function getPricePerFullShare() external view returns (uint256); ``` - - | | | type | desc | | ------ | --- | ------- | ---------------------------------------------------------------------------- | | Output | 0 | uint256 | Price of the Vault’s wrapped token denominated in the unwrapped native token | @@ -297,16 +207,10 @@ function getPricePerFullShare() external view returns (uint256); Deposits the specified amount of the native unwrapped token (same as `token()` returns) into the Vault. - - ```javascript function deposit(uint256) external; ``` - - | | | type | desc | | ----- | --- | ------- | --------------------------------- | | Input | 0 | uint256 | Amount to deposit into the Vault. | @@ -315,30 +219,18 @@ function deposit(uint256) external; Deposits the maximum available amount of the native unwrapped token (same as `token()` returns) into the Vault. - - ```javascript function depositAll() external; ``` - - ### function `withdraw()` Withdraws the specified amount of the native unwrapped token (same as `token()` returns) from the Vault. - - ```javascript function withdraw(uint256) external; ``` - - | | | type | desc | | ----- | --- | ------- | ---------------------------------- | | Input | 0 | uint256 | Amount to withdraw from the Vault. | @@ -347,16 +239,10 @@ function withdraw(uint256) external; Withdraws the maximum available amount of the native unwrapped token (same as `token()` returns) from the Vault. - - ```javascript function withdrawAll() external; ``` - - ## IController Source code: [yearn-protocol/develop/interfaces/yearn/IController.sol](https://github.com/yearn/yearn-protocol/blob/develop/interfaces/yearn/IController.sol) @@ -365,16 +251,10 @@ Source code: [yearn-protocol/develop/interfaces/yearn/IController.sol](https://g Calls `Strategy.withdraw()` function for the amount defined in `unit256` in the Strategy of the specified address. This function should have access control enforcing the Vault to be its only allowed caller. - - ```javascript function withdraw(address, uint256) external; ``` - - | | | type | desc | | ----- | --- | ------- | ---------------------------------------- | | Input | 0 | address | Address of the Strategy to withdraw from | @@ -384,16 +264,10 @@ function withdraw(address, uint256) external; Returns the Strategy's balance of the specified token. - - ```javascript function balanceOf(address) external view returns (uint256); ``` - - | | | type | desc | | ------ | --- | ------- | ---------------------------------- | | Input | 0 | address | Token that is used in the Strategy | @@ -403,16 +277,10 @@ function balanceOf(address) external view returns (uint256); Transfers the profits earned from the yield generating activities of the Strategy to the Vault. Takes an address of a token to withdraw and an amount. - - ```javascript function earn(address, uint256) external; ``` - - | | | type | desc | | ----- | --- | ------- | ---------------------------------------------------- | | Input | 0 | address | Token to be withdrawn to the Vault from the Strategy | @@ -424,30 +292,18 @@ function earn(address, uint256) external; Not used by the currently deployed controller. Please refer to [`Strategy.want()`](#function-want) instead. - - ```javascript function want(address) external view returns (address); ``` - - ### function `rewards()` Returns the address of the Treasury which is where the system reward fees go. - - ```javascript function rewards() external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | ----------------- | | Output | 0 | address | Treasury contract | @@ -456,16 +312,10 @@ function rewards() external view returns (address); Takes a token address and returns the corresponding Vault address. - - ```javascript function vaults(address) external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | --------------------------------------------------------- | | Input | 0 | address | Token to find a Vault address for | @@ -475,16 +325,10 @@ function vaults(address) external view returns (address); Takes a token address and returns the corresponding Strategy address. - - ```javascript function strategies(address) external view returns (address); ``` - - | | | type | desc | | ------ | --- | ------- | ------------------------------------------------------------ | | Input | 0 | address | Token to find a Strategy address for | diff --git a/docs/developers/wallet-integration.md b/docs/developers/wallet-integration.md new file mode 100644 index 000000000..f79671e7c --- /dev/null +++ b/docs/developers/wallet-integration.md @@ -0,0 +1,300 @@ +# Wallet and Portfolio Tracker Integration + +Yearn and its ecosystem contain a number of different vaults and products that can be hard to keep up with. This guide will describe the best way to accurately and effectively find Yearn vaults and other products to keep your users in the know when it comes to their positions. This page will cover finding all of Yearn's vaults, determining accurate prices for them and how to show historical APYs. + +## Overview + +There are 2 ways to get Yearn Vault Data: Via the [Kong API](/developers/data-services/yearn-data/#kong) that Yearn provides or manually by querying the smart contracts used to deploy and register Vaults. We will start by looking at how to do this manually to give an overview of how the system works. + +Yearn has a few versions of Vaults: [V1](/developers/v1/introduction), [V2](/developers/v2/getting-started), and [V3](/developers/v3/overview) and each will need to be queried slightly differently. We will start with V3. + +## Getting V2 and V3 Vaults with Kong + +Being able to get the vaults manually is great, but here at Yearn we like to make things easy. So we have a public endpoint for the Yearn-built [Kong](/developers/data-services/yearn-data/#kong) indexer that you can query for all V2 and V3 Yearn vaults (and you can also get other 4626 vaults with it!). + +The public endpoint is: https://kong.yearn.farm/api/gql + +As of writing there is no need for an API key and the API can be queried with standard graphQL libraries The example below use Apollo client, but the concept should be similar for all libraries. The above link is also an explorer to play around with the endpoint. The documentation is still under construction, but below you will get the basics. + +```markdown title="Example Vault Query" + query GetVaultData { + vaults { + address + name + chainId + asset { + name + symbol + decimals + address + } + yearn + v3 + meta { + displayName + displaySymbol + description + protocols + token { + category + description + displayName + displaySymbol + icon + type + } + } + apy { + weeklyNet + } + pricePerShare + } + } +``` + +The above query will retrieve all vaults from Kong with the following fields for each: + +- `address` (The vault address) +- `name` (The vault name) +- `chainId` (The chain ID the vault lives on) +- `asset` (The name, symbol, number of decimals, and address of the underlying asset the vault contains) +- `yearn` (A boolean value for whether the vault is endorsed or not) +- `v3` (A boolean value for whether the vault is a v3 vault or not) +- `meta` (Assorted metadata for the vault including descriptions of the vault and/or underlying tokens). This data exists for most Yearn deployed vaults but not all. +- `apy` (the current APY of the vault. There are other ways to get APY we will discuss below). +- `pricePerShare` (the current price per Vault Share) + +The returned list of vaults will include all v2 and v3 vaults as well as many popular ERC4626 vaults deployed on ethereum and other L2s. If you want to limit your result to just endorsed vaults, you will need to filter the resulting object on the `yearn` boolean. + +```js title="Example pseudo-code" +const filterYearnVaults = (vaults) => + vaults.filter((vault) => vault.yearn) + +const data = Query(getVaultData) +const yearnVaults = data?.vaults ? filterYearnVaults(data.vaults) : undefined +``` + +There are lots more fields to query over so take a look around in the playground and pop into the Yearn discord if you have any questions. + +## Getting V3 yVaults Manually + +Below are the relevant factories and registries for V3 contracts. The most recent registry will always be located at registry.v3.ychad.eth. All deployments are done using Create2 factories so these addresses will be consistent across all EVM chains. + +| Registry / ENS | Contract Address | +| ---------------------- | ---------------------- | +| **VaultFactory 3.0.1** | | +| **VaultFactory 3.0.2** | | +| **VaultFactory 3.0.3** | | +| **VaultFactory 3.0.4** | | +| **V3 Registry**
registry.v3.ychad.eth | | +| **Legacy V3 Registry**
| | + +A full list of yVault V3 contracts can be viewed [here](/developers/addresses/v3-contracts). The addresses on that page are stored in a `constants.ts` file located in the yearn DevDocs repo. You can find it [here](https://github.com/yearn/yearn-devdocs/blob/master/src/ethereum/constants.ts). + +### Querying Factories + +:::info + +If you only want to get "official" or endorsed Yearn vaults, then skip this section and just go to the "Querying Registries" section below. + +::: + +Yearn's V3 Vault Factory contracts are deployed on many EVM chains and are permissionless, so anyone can use them to create vaults. If you want to find all vaults that have been deployed, whether it was done by Yearn or not, you need to look at the Factory Vaults. + +When a new vault is created with a factory, the factory emits a `NewVault` event to the logs that includes the vault address and the address of the underlying asset in the vault (i.e. USDC). + +```solidity +NewVault (index_topic_1 address vault_address, index_topic_2 address asset) +``` + +Each new version of Vaults that are deployed will have its own factory, and each factory will have its own logs of events, so to get all of the deployed vaults you will need to iterate over all the factories. + +### Querying Registries + +Since V3 factories are permissionless, Yearn also deploys permissioned registry contracts that only Yearn governance can add to. These are the best place to find the official (endorsed) Yearn Vaults that are deployed by Yearn. As mentioned above, the most recent registry will resolve from registry.v3.ychad.eth. But you will need to query all the registries to get all the endorsed vaults. + +To get the endorsed vaults, you can either: + +**A.** Search through the Events Log of the registry contract and save all `NewEndorsedVault` events. This data contains the vault address, the underlying asset address, the release Version, and the Vault Type. + +```solidity +NewEndorsedVault (index_topic_1 address vault, index_topic_2 address asset, uint256 releaseVersion, uint256 vaultType) +``` + +**B.** Or query the registry factory directly. To do that, you need to: + +1. Call the `getAssets()` function to get an array of underlying tokens with deployed vaults. This array will be used in the next step. +2. Loop through each entry in the array and call the `getEndorsedVaults()` function with the address value from the array as the argument to get an array of vaults for each underlying asset + +```js title="Example pseudo-code" +const allVaultsFromRegistry = [] +const assetArray = getAssets() +for (asset in assetArray) { + const vaultsArray = getEndorsedVaults(asset) + allVaultsFromRegistry.push(...vaultsArray) +} +``` + +Additional vault data can then be found by calling the respective read functions on the vault contracts (`name()`, `symbol()`, `decimals()`, `token()`, `pricePerShare()`, etc.). + +Like the factories, you will need to query all registry contracts to get all the endorsed vaults. + +## Getting V2 yVaults Manually + +Below are the relevant registries for V2 contracts. + +| Registry / ENS | Chain (ID) | Contract Address | +|----------------|------------|------------------| +| **Mainnet Factory Registry**
factory.ychad.eth | 1 | 0xaF1f5e1c19cB68B30aAD73846eFfDf78a5863319 | +| **Mainnet Legacy Registry 1** | 1 | 0xe15461b18ee31b7379019dc523231c57d1cbc18c | +| **Mainnet Legacy Registry 2** | 1 | 0x50c1a2eA0a861A967D9d0FFE2AE4012c2E053804 | +| **Optimism Factory Registry** | 10 | 0x79286Dd38C9017E5423073bAc11F53357Fc5C128 | +| **Optimism Legacy Registry** | 10 | 0x1ba4eB0F44AB82541E56669e18972b0d6037dfE0 | +| **Fantom Legacy Registry** | 250 | 0x727fe1759430df13655ddb0731dE0D0FDE929b04 | +| **Arbitrum Factory Registry** | 42161 | 0x84654e35E504452769757AAe5a8C7C6599cBf954 | +| **Arbitrum Legacy Registry** | 42161 | 0x3199437193625DCcD6F9C9e98BDf93582200Eb1f | +| **Base Factory Registry** | 8453 | 0xF3885eDe00171997BFadAa98E01E167B53a78Ec5 | + +V2 works similarly to V3 in that there is a factory contract (called the Release Registry) where anyone can deploy a vault. There is also a Vault registry contract that stores the endorsed Yearn vaults (called the Factory Registry). A full list of yVault V2 contracts can be viewed [here](/developers/addresses/v2-contracts). + +Endorsed vaults can be queried directly from this Vault Registry contract. To do that you need to: + +1. Call the `numTokens()` function to get the number of underlying tokens with deployed vaults. This will be used as the index for the next step. +2. Loop through each entry in the index and call the `tokens()` function with the index value as the argument to get the underlying token address at that index point. +3. For each underlying token address, call `numVaults()` with the address as the argument. This will be used as the index for the next step. +4. Loop through each entry in the new index and call the `vaults()` function with the underlying token address and index value as the arguments. + +```js title="Example pseudo-code" +const allV2VaultsFromRegistry = [] +const numTokens = numtokens() +for (i=0, i < numtokens-1, i++){ + const tknAddress = tokens(i) + const numberOfVaults = numVaults(tknAddress) + for (v=0, v < numberOfVaults-1, v++){ + const vaultAddress = vaults(tknAddress, v) + allVaultsFromRegistry.push(vaultAddress) + } +} +``` + +Additional vault data can then be found by calling the respective read functions on the vault contracts (`name()`, `symbol()`, `decimals()`, `token()`, `pricePerShare()`, etc). + +Like with V3, you will need to query all registry contracts to get all the endorsed vaults. + +## Getting V1 Vaults + +Unfortunately, Kong does not index V1 vaults (yet) as they have long ago been deprecated. That doesn't mean that there aren't still funds deposited in them that users may want to get out. Like V2 and V3, there is a registry for all v1 vaults: + +| Registry / ENS | Contract Address | +| ---------------------- | ---------------------- | +| V1 vault registry
registry.ychad.eth | https://etherscan.io/address/0x3eE41C098f9666ed2eA246f4D2558010e59d63A0 | + +V1 was permissioned so all vaults are "endorsed". To get the vaults: + +1. Call `getVaultsLength()` to get the number of vaults in the registry. This will be used as the index for the next step. +2. loop through each entry in the index and call the `getVault()` function with the index value as the argument + +```js title="Example pseudo-code" +const allV1VaultsFromRegistry = [] +const numVaults = getVaultsLength() +for (i=0, i < numtokens-1, i++){ + const vaultAddress = getVault(i) + allV1VaultsFromRegistry.push(vaultAddress) +} +``` + +Additional vault data can then be found by calling the respective read functions on the vault contracts (`name()`, `symbol()`, `decimals()`, `getPricePerFullShare()`, etc). + +## Vault Prices + +Now that you have the vaults, you are going to need to price them. Yearn vaults use the standard ERC4626 vault share pattern where depositors receive a number of vault shares when they deposit that represent their share of the pool total. As yield is harvested and returned to the vault, the vault share values increase and the underlying value of tokens the user can withdraw also increases. + +To get the value of a deposit into a vault, you need to multiply the number of vault shares held by the user (or contract) by the price per share. All Yearn vault contracts have a `pricePerShare()` read function that is denominated in the underlying asset and can be called to get the price per share. + +1. Query `balanceOf()` with the user address. +2. Query `pricePerShare()` or get the value from your Kong query. +3. Query `decimals()` or get the value from your Kong query. +4. multiply the value returned from `balanceOf()` by the value returned from `pricePerShare()` and divide by 10 to the power of the value returned from `decimals()`. + +```js +const shareBalance = balanceOf(userAddress) +const pricePerShare = pricePerShare() +const decimals = decimals() + +const valueInUnderlying = (shareBalance * pricePerShare) / (10 ** decimals) +``` + +Boom, now you have vault prices and the value of your user's positions. + +## Calculating APYs + +:::info + +APR? APY? What's the difference? [This article](https://www.investopedia.com/personal-finance/apr-apy-bank-hopes-cant-tell-difference/) explains it in depth, but the gist is APR does not include compounding (reinvestment) while APY does. APY tends to be more accurate when determining interest earned over longer periods since the interest compounds to earn additional interest. + +::: + +Once again, the easiest way to get APY data is using Kong. The vault query in the [vaults section](#getting-v2-and-v3-vaults-with-kong) includes the APY from the last week. The other options are: + +- `grossAPR`: the APR rate reversed engineered from calculated APY. This number does not have fees taken out. +- `net`: APY value calculated from the change in the pricePerShare (PPS) over a certain time period. It uses `monthlyNet` for mainnet vaults and `weeklyNet` for all other chains. +- `weeklyNet`: The net APY (yield minus fees) based on the change in PPS over the last week, annualized, with compounding extrapolated from the harvest frequency over the last 7 days. +- `monthlyNet`: The net APY (yield minus fees) based on the change in PPS over the last month, annualized, with compounding extrapolated from the harvest frequency over the last 30 days. +- `inceptionNet`: The net APY (yield minus fees) based on the change in PPS since vault creation. + +:::info + +The APY you get from Kong is an accurate, backward-looking APY calculated from the change in value of the vault. They do not incorporate any forward looking projections. The `grossAPR` number from Kong is calculated from the APY and does account for fees that will be taken out. It is different from the APRs discussed below from the AprOracle. + +::: + +Kong can also serve historical APYs. To get those you will need to use a timeseries. Here is an [example](https://kong.yearn.farm/api/gql?explorerURLState=N4IgJg9gxgrgtgUwHYBcQC4QAIsEcYIBOAnlgIIAOxAigSQBQA6SOOAJADYCGARgh%2BiwBlFIQCWSAOYBCZqyxsuYMIQQBnNYJHipc1pzFwxKQQElUe9lAhwKEJMhPDREyXoCUWYJawpD6ojF1JhZ5LG4%2BAQUI-h8cJRV1TQUE1Q048MNjQQMjFAzrW3tHHMK7BwtQnE9vKtYoAAsuCVMwDNSkjJiOAptyxwyKQIg2upw-RAyANy4OAh8AXz0FkAAaEBnxXg51DBBvQj1GEA70jCxjgAYAD0uAdgAWAEYAZgeyACY7gA4HgDF-gA2QE8QFQBAAEUBADNAd9fgBOF7fD4IhGXP7Ql4fJ4AVmOq0Yh1Cx26x0Exy4VAAtDwAO5galgfgoLjUigUNQEolHEBlYoWc7HBz5NY8kkgDhZUWCJ6XeXilYLIA): + +```markdown + query ApyQuery( + $label: String! + $address: String + $limit: Int + $component: String + ) { + timeseries( + label: $label + address: $address + limit: $limit + component: $component + ) { + chainId + address + label + component + period + time + value + } + } + ``` + +The above query will need to be made with variables passed into it + +- address: the vault address as a string +- label: 'apy-bwd-delta-pps' is the label for APY queries. +- component?: this is APY time period mentioned above like 'net' +- limit?: number of results to return (1000 is a good number) + +The above query will give daily values for the `weeklyAPY` value for a chosen vault. + +## Calculating APRs from on-chain APR Oracles + +:::info + +The data from an APR oracle is a current APR and does not include compounding like the historical data from Kong. It is both a snapshot of the current APR and also gives an expected APR into the near future since it reads reward assets that are being streamed into the vault. + +::: + +V3 vaults have an APR oracle that can be queried to get current APR values calculated from the yield unlocking on the contracts. As of writing, this contract is [0x1981AD9F44F2EA9aDd2dC4AD7D075c102C70aF92](https://etherscan.io/address/0x1981AD9F44F2EA9aDd2dC4AD7D075c102C70aF92). This can be manually checked by calling the `getAprOracle()` view function on the Protocol Address Provider: . + +You can read more about the APR Oracle contracts [here](/developers/smart-contracts/V3/Periphery/AprOracle). + +## Conclusion + +You should now have a solid foundation for incorporating Yearn vaults into your wallet or portfolio tracker. Yearn is constantly building, so if you encounter any issues with the above, or are looking for additional support, come pop in to the `dev-open-chat` channel our [discord](https://discord.gg/yearn). diff --git a/scripts/fetchedAddressData.json b/scripts/fetchedAddressData.json index 67fadef01..e0ecd0e30 100644 --- a/scripts/fetchedAddressData.json +++ b/scripts/fetchedAddressData.json @@ -1,5 +1,6 @@ { - "timeLastChecked": 1732226783, + "timeLastChecked": 1736294978, + "addressesData": { "topLevel": { "v3ProtocolAddressProvider": "0x775F09d6f3c8D2182DFA8bce8628acf51105653c", diff --git a/sidebars/sidebarsDeveloperDocs.js b/sidebars/sidebarsDeveloperDocs.js index c5d7f72f2..f816998b4 100644 --- a/sidebars/sidebarsDeveloperDocs.js +++ b/sidebars/sidebarsDeveloperDocs.js @@ -77,13 +77,7 @@ export default { type: 'doc', id: 'v1/introduction', }, - items: [ - { - type: 'link', - label: 'Smart Contracts →', - href: 'https://docs.yearn.fi/developers/smart-contracts/v1/interfaces', // this link needs to be hardcoded to not cause issues with the sidebar - }, - ], + items: ['v1/interfaces'], }, 'v2/naming-convention', ], @@ -122,7 +116,11 @@ export default { type: 'doc', id: 'front-end-development', }, - items: ['data-services/yearn-stack', 'v2/fork-yearn-ui'], + items: [ + 'wallet-integration', + 'data-services/yearn-stack', + 'v2/fork-yearn-ui', + ], }, // Other Stuff { @@ -253,17 +251,12 @@ export default { }, ], }, - // { - // type: 'category', - // label: 'V1 Vaults', - // collapsed: true, - // items: [ - // { - // type: 'autogenerated', - // dirName: 'smart-contracts/V1', - // }, - // ], - // }, + { + type: 'category', + label: 'V1 Vaults', + collapsed: true, + items: ['v1/interfaces'], + }, { type: 'link', label: 'Yearn Lens →', diff --git a/src/ethereum/constants.ts b/src/ethereum/constants.ts index 3be983506..7fd2eac73 100644 --- a/src/ethereum/constants.ts +++ b/src/ethereum/constants.ts @@ -2,6 +2,8 @@ * Ethereum Contracts */ +//TODO add v2 and v2 contracts + export const yfiContracts = { // YFI Contracts yfiAddress: '0x0bc529c00C6401aEF6D220BE8C6Ea1667F6Ad93e', @@ -82,6 +84,7 @@ export const yearnV3Contracts = { accountant: '0x5A74Cb32D36f2f517DB6f7b0A0591e09b22cDE69', registryENS: 'registry.v3.ychad.eth', registry: '0xd40ecF29e001c76Dcc4cC0D9cd50520CE845B038', + legacyRegistry1: '0xff31A1B020c868F6eA3f61Eb953344920EeCA3af', debtAllocator: '0x1e9eB053228B1156831759401dE0E115356b8671', keeper: '0x52605BbF54845f520a3E94792d019f62407db2f8', daddy: '0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52',