From eda73853ba53ddac7be5b83346e21eb31da37a2b Mon Sep 17 00:00:00 2001 From: jstashh <19509999+jstashh@users.noreply.github.com> Date: Wed, 25 May 2022 14:31:46 +0100 Subject: [PATCH] feat: add vault info to vault interface (#290) Description Adds a getInfo method to the vault interface which allows fetching basic data about the vault in one call, can be extended in the future if more info is needed. An example of the data provided: { name: 'Curve MIM Pool Vault', symbol: 'yvCurve-MIM', apiVersion: '0.4.3', emergencyShutdown: false, lastReport: 2022-05-23T12:48:47.000Z, managementFee: BigNumber { _hex: '0xc8', _isBigNumber: true }, performanceFee: BigNumber { _hex: '0x07d0', _isBigNumber: true }, totalAssets: BigNumber { _hex: '0x01ef9f3f4483e5456c54', _isBigNumber: true }, depositLimit: BigNumber { _hex: '0x084595161401484a000000', _isBigNumber: true }, debtRatio: BigNumber { _hex: '0x2710', _isBigNumber: true }, management: '0x727fe1759430df13655ddb0731dE0D0FDE929b04', governance: '0xC0E2830724C946a6748dDFE09753613cd38f6767', guardian: '0x72a34AbafAB09b15E7191822A679f28E067C4a16', rewards: '0x89716Ad7EDC3be3B35695789C475F3e7A3Deb12a' } Motivation and Context Adding more functionality to the SDK for rendering data about vaults/strategies. How Has This Been Tested? Added unit test --- src/interfaces/vault.spec.ts | 60 ++++++++++++++++++++++++++++ src/interfaces/vault.ts | 45 +++++++++++++++++++++ src/services/propertiesAggregator.ts | 2 +- src/types/custom/vault.ts | 18 +++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) diff --git a/src/interfaces/vault.spec.ts b/src/interfaces/vault.spec.ts index 31d33d38..60b5bf1a 100644 --- a/src/interfaces/vault.spec.ts +++ b/src/interfaces/vault.spec.ts @@ -66,6 +66,7 @@ const assetsHistoricEarningsMock = jest.fn(); const sendTransactionUsingServiceMock = jest.fn(); const partnerPopulateDepositTransactionMock = jest.fn(); const partnerIsAllowedMock = jest.fn().mockReturnValue(true); +const propertiesAggregatorGetPropertiesMock = jest.fn(); jest.mock("../services/partner", () => ({ PartnerService: jest.fn().mockImplementation(() => ({ @@ -78,6 +79,9 @@ jest.mock("../services/partner", () => ({ jest.mock("../yearn", () => ({ Yearn: jest.fn().mockImplementation(() => ({ services: { + propertiesAggregator: { + getProperties: propertiesAggregatorGetPropertiesMock, + }, meta: { vaults: metaVaultsMock, }, @@ -1053,4 +1057,60 @@ describe("VaultInterface", () => { }); }); }); + + describe("getInfo", () => { + it("should return values from property aggregator", async () => { + const lastReportTimestamp = 1653392108; + const lastReportDate = new Date(lastReportTimestamp * 1000); + + const name = "name"; + const symbol = "symbol"; + const apiVersion = "0.3.5"; + const emergencyShutdown = false; + const managementFee = BigNumber.from(200); + const performanceFee = BigNumber.from(2000); + const totalAssets = BigNumber.from(123); + const depositLimit = BigNumber.from(456); + const debtRatio = BigNumber.from(10000); + const management = "0x727fe1759430df13655ddb0731dE0D0FDE929b04"; + const governance = "0xC0E2830724C946a6748dDFE09753613cd38f6767"; + const guardian = "0x72a34AbafAB09b15E7191822A679f28E067C4a16"; + const rewards = "0x89716Ad7EDC3be3B35695789C475F3e7A3Deb12a"; + + const propertiesAggregatorReturnValue = { + lastReport: BigNumber.from(lastReportTimestamp), + name, + symbol, + apiVersion, + emergencyShutdown, + managementFee, + performanceFee, + totalAssets, + depositLimit, + debtRatio, + management, + governance, + guardian, + rewards, + }; + + propertiesAggregatorGetPropertiesMock.mockReturnValue(propertiesAggregatorReturnValue); + + const result = await vaultInterface.getInfo("0x1e2fe8074a5ce1Bb7394856B0C618E75D823B93b"); + expect(result.lastReport).toEqual(lastReportDate); + expect(result.name).toEqual(name); + expect(result.symbol).toEqual(symbol); + expect(result.apiVersion).toEqual(apiVersion); + expect(result.emergencyShutdown).toEqual(emergencyShutdown); + expect(result.managementFee).toEqual(managementFee); + expect(result.performanceFee).toEqual(performanceFee); + expect(result.totalAssets).toEqual(totalAssets); + expect(result.depositLimit).toEqual(depositLimit); + expect(result.debtRatio).toEqual(debtRatio); + expect(result.management).toEqual(management); + expect(result.governance).toEqual(governance); + expect(result.guardian).toEqual(guardian); + expect(result.rewards).toEqual(rewards); + }); + }); }); diff --git a/src/interfaces/vault.ts b/src/interfaces/vault.ts index 537c4f15..1ee249b4 100644 --- a/src/interfaces/vault.ts +++ b/src/interfaces/vault.ts @@ -1,3 +1,4 @@ +import { ParamType } from "@ethersproject/abi"; import { BigNumber } from "@ethersproject/bignumber"; import { MaxUint256 } from "@ethersproject/constants"; import { CallOverrides, Contract, PopulatedTransaction } from "@ethersproject/contracts"; @@ -19,6 +20,7 @@ import { TokenAllowance, TokenMetadata, VaultDynamic, + VaultInfo, VaultMetadataOverrides, VaultStatic, VaultsUserSummary, @@ -544,6 +546,49 @@ export class VaultInterface extends ServiceInterface { } } + /** + * Fetches information a vault in a single call + * @param vaultAddress the vault to query's address + * @returns a `VaultInfo` object which includes various information about a vault, for example, its name and total assets + */ + async getInfo(vaultAddress: Address): Promise { + const properties = [ + "string name", + "string symbol", + "string apiVersion", + "bool emergencyShutdown", + "uint256 lastReport", + "uint256 managementFee", + "uint256 performanceFee", + "uint256 totalAssets", + "uint256 depositLimit", + "uint256 debtRatio", + "address management", + "address governance", + "address guardian", + "address rewards", + ].map((prop) => ParamType.from(prop)); + + const result = await this.yearn.services.propertiesAggregator.getProperties(vaultAddress, properties); + + return { + name: result.name as string, + symbol: result.symbol as string, + apiVersion: result.apiVersion as string, + emergencyShutdown: result.emergencyShutdown as boolean, + lastReport: new Date((result.lastReport as BigNumber).mul(BigNumber.from(1000)).toNumber()), + managementFee: result.managementFee as BigNumber, + performanceFee: result.performanceFee as BigNumber, + totalAssets: result.totalAssets as BigNumber, + depositLimit: result.depositLimit as BigNumber, + debtRatio: result.debtRatio as BigNumber, + management: result.management as Address, + governance: result.governance as Address, + guardian: result.guardian as Address, + rewards: result.rewards as Address, + }; + } + private async zapIn( vault: Address, token: Address, diff --git a/src/services/propertiesAggregator.ts b/src/services/propertiesAggregator.ts index 2c6841bd..e667ddcd 100644 --- a/src/services/propertiesAggregator.ts +++ b/src/services/propertiesAggregator.ts @@ -5,7 +5,7 @@ import { ChainId } from "../chain"; import { ContractAddressId, ContractService, WrappedContract } from "../common"; import { Address } from "../types"; -type DecodingType = string | BigNumber; +type DecodingType = string | BigNumber | boolean; /** * [[PropertiesAggregatorService]] allows queries of a contract's methods to be aggregated into one diff --git a/src/types/custom/vault.ts b/src/types/custom/vault.ts index 68726761..030a5ed5 100644 --- a/src/types/custom/vault.ts +++ b/src/types/custom/vault.ts @@ -1,3 +1,4 @@ +import { BigNumber } from "@ethersproject/bignumber"; import { PartialDeep } from "type-fest"; import { Vault } from ".."; @@ -73,3 +74,20 @@ export type ZappableVault = { pricePerShare: Integer; }; } & PartialDeep; + +export interface VaultInfo { + name: string; + symbol: string; + apiVersion: string; + emergencyShutdown: boolean; + lastReport: Date; + managementFee: BigNumber; + performanceFee: BigNumber; + totalAssets: BigNumber; + depositLimit: BigNumber; + debtRatio: BigNumber; + management: Address; + governance: Address; + guardian: Address; + rewards: Address; +}