Skip to content

Commit

Permalink
feat: support VaultsV2 adapter & IronBank adapter
Browse files Browse the repository at this point in the history
  • Loading branch information
nymmrx committed May 13, 2021
1 parent 523f8d9 commit d5c7d64
Show file tree
Hide file tree
Showing 14 changed files with 397 additions and 1,152 deletions.
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v15.12.0
v14.17.0
54 changes: 39 additions & 15 deletions examples/mvp.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,22 @@ const { Yearn } = require("../dist");
const url = process.env.WEB3_PROVIDER || "http://localhost:8545";
const provider = new JsonRpcProvider(url);

const yearn = new Yearn(1, { provider });
const yearn = new Yearn(1, {
provider,
addresses: {
adapters: {
registryV2: "0xFbD588c72B438faD4Cf7cD879c8F730Faa213Da0",
ironBank: "0xed00238F9A0F7b4d93842033cdF56cCB32C781c2"
},
helper: "0x420b1099B9eF5baba6D92029594eF45E19A04A4A",
oracle: "0xE7eD6747FaC5360f88a2EFC03E00d25789F69291"
}
});

async function main() {
// Get all vaults in the current network
const gov = "0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52";

// VAULTS V1 & V2
const vaults = await yearn.vaults.get();

const vaultsTable = new Table();
Expand All @@ -19,17 +31,6 @@ async function main() {
console.log("V1 & V2 vaults:");
console.log(vaultsTable.toString());

// Get all vaults in the current network
const ironBank = await yearn.ironBank.get();

const ironBankTable = new Table();
ironBankTable.push(...ironBank.map(market => [market.name, market.address, market.typeId]));

console.log("IronBank markets:");
console.log(ironBankTable.toString());

// Get position of user for all the assets in this network
const gov = "0xFEB4acf3df3cDEA7399794D0869ef76A6EfAff52";
const positions = await yearn.vaults.positionsOf(gov);

const positionsTable = new Table();
Expand All @@ -40,10 +41,33 @@ async function main() {
})
);

console.log("Yearn Multisig positions:");
console.log("Yearn Multisig vault positions:");
console.log(positionsTable.toString());

// // ONLY ETH
// IRON BANK
const ironBank = await yearn.ironBank.get();

const ironBankTable = new Table();
ironBankTable.push(...ironBank.map(market => [market.name, market.address, market.typeId]));

console.log("IronBank markets:");
console.log(ironBankTable.toString());

const ironBankGeneralPositionTable = new Table();
const ironBankGeneralPosition = await yearn.ironBank.generalPositionOf(gov);

ironBankGeneralPositionTable.push(...Object.entries(ironBankGeneralPosition));
console.log("Yearn Multisig general IronBank position:");
console.log(ironBankGeneralPositionTable.toString());

const ironBankUserMetadataTable = new Table();
const ironBankUserMetadata = await yearn.ironBank.userMetadata(gov);

ironBankUserMetadataTable.push(...ironBankUserMetadata.map(market => Object.values(market)));
console.log("Yearn Multisig IronBank user metadata:");
console.log(ironBankUserMetadataTable.toString());

// ONLY ETH

// Get all tokens supported by zapper
const yfiVault = vaults.find(vault => vault.name === "YFI yVault").address;
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
"@types/object-hash": "^2.1.0",
"apollo": "^2.33.0",
"cli-table3": "^0.6.0",
"release-it": "^14.6.1",
"size-limit": "^4.10.1",
"tsdx": "^0.14.1",
"tslib": "^2.1.0",
Expand All @@ -52,7 +51,8 @@
"events": "^3.3.0",
"graphql": "^15.5.0",
"graphql-tag": "^2.12.4",
"object-hash": "^2.1.1"
"object-hash": "^2.1.1",
"type-fest": "^1.1.1"
},
"publishConfig": {
"access": "public"
Expand All @@ -67,8 +67,8 @@
"limit": "80 KB"
}
],
"engines" : {
"node" : ">=12.0.0"
"engines": {
"node": ">=12.0.0"
},
"prettier": {
"endOfLine": "auto",
Expand Down
2 changes: 1 addition & 1 deletion src/abi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ export const AdapterAbi = (Metadata: string) => [
`function assetsDynamic(address[] memory) public view returns (${AssetDynamicAbi(Metadata)}[] memory)`,
`function assetsPositionsOf(address) public view returns (${PositionAbi}[] memory)`,
`function assetsPositionsOf(address, address[] memory) public view returns (${PositionAbi}[] memory)`,
`function tokens() public view returns (${TokenAbi}[] memory)`
`function assetsTokensAddresses() public view returns (address[] memory)`
];
6 changes: 5 additions & 1 deletion src/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,11 @@ export class Service {
if (res && res instanceof Promise) {
res
.then(result => {
this.events.emit(method.name, result);
try {
this.events.emit(method.name, result);
} catch (error) {
throw new SdkError(`${path} (event listener): ${error.message}`);
}
return result;
})
.catch(error => {
Expand Down
18 changes: 9 additions & 9 deletions src/context.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
import { PartialDeep } from "type-fest";
import { Provider } from "@ethersproject/providers";

import { CacheManager, Cache } from "./cache";

import { Address, SdkError } from "./common";

export interface AddressesOverride {
lens?: Address;
oracle?: Address;
registryV2Adapter?: Address;
ironBankAdapter?: Address;
adapters: {
registryV2?: Address;
ironBank?: Address;
};
helper?: Address;
}

export interface ContextValue {
provider?: Provider;
zapper?: string;
etherscan?: string;
addresses?: AddressesOverride;
addresses?: PartialDeep<AddressesOverride>;
}

export class Context implements Required<ContextValue> {
Expand Down Expand Up @@ -46,11 +51,6 @@ export class Context implements Required<ContextValue> {
}

get addresses(): AddressesOverride {
if (this.ctx.addresses) return this.ctx.addresses;
return {};
}

address(service: keyof AddressesOverride): Address | undefined {
return this.addresses[service];
return Object.assign({ adapters: {} }, this.ctx.addresses);
}
}
5 changes: 3 additions & 2 deletions src/readers/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ export class TokenReader<C extends ChainId> extends Reader<C> {
const adapters = Object.values(this.yearn.services.lens.adapters.vaults);
const vaults = await Promise.all(
adapters.map(async adapter => {
const tokens = await adapter.tokens();
const icons = this.yearn.services.icons.get(tokens.map(({ address }) => address));
const tokenAddresses = await adapter.tokens();
const tokens = await this.yearn.services.helper.tokens(tokenAddresses);
const icons = this.yearn.services.icons.get(tokenAddresses);
return Promise.all(
tokens.map(async token => ({
...token,
Expand Down
19 changes: 8 additions & 11 deletions src/services/adapters/ironbank.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,16 @@ import { AdapterAbi } from "../../abi";
import { ChainId } from "../../chain";
import { Address, ContractService } from "../../common";
import { Context } from "../../context";
import { structArray } from "../../struct";
import { struct, structArray } from "../../struct";

import {
Position,
IronBankMarketStatic,
IronBankMarketDynamic,
ERC20,
IronBankPosition,
CyTokenUserMetadata
} from "../../types";

export interface IronBank {}

const CyTokenMetadataAbi = `tuple(
uint256 totalSuppliedUsdc,
uint256 totalBorrowedUsdc,
Expand All @@ -25,7 +22,7 @@ const CyTokenMetadataAbi = `tuple(
uint256 collateralFactor,
bool isActive,
uint256 reserveFactor,
uint256 collateralFactor
uint256 exchangeRate
)`;

const CyTokenUserMetadataAbi = `tuple(
Expand All @@ -44,15 +41,15 @@ const IronBankPositionAbi = `tuple(
)`;

const CustomAbi = [
`adapterPositionOf(address) external view returns (${IronBankPositionAbi} memory)`,
`assetsUserMetadata(address) public view returns (${CyTokenUserMetadataAbi}[] memory)`
`function adapterPositionOf(address) external view returns (${IronBankPositionAbi} memory)`,
`function assetsUserMetadata(address) public view returns (${CyTokenUserMetadataAbi}[] memory)`
];

export class IronBankAdapter<T extends ChainId> extends ContractService {
static abi = AdapterAbi(CyTokenMetadataAbi).concat(CustomAbi);

constructor(chainId: T, ctx: Context) {
super(ctx.address("ironBankAdapter") ?? IronBankAdapter.addressByChain(chainId), chainId, ctx);
super(ctx.addresses.adapters.ironBank ?? IronBankAdapter.addressByChain(chainId), chainId, ctx);
}

static addressByChain(chainId: ChainId): string {
Expand Down Expand Up @@ -87,14 +84,14 @@ export class IronBankAdapter<T extends ChainId> extends ContractService {
}

async generalPositionOf(address: Address): Promise<IronBankPosition> {
return await this.contract.adapterPositionOf(address).then(structArray);
return await this.contract.adapterPositionOf(address).then(struct);
}

async assetsUserMetadata(address: Address): Promise<CyTokenUserMetadata[]> {
return await this.contract.assetsUserMetadata(address).then(structArray);
}

async tokens(): Promise<ERC20[]> {
return await this.contract.tokens().then(structArray);
async tokens(): Promise<Address[]> {
return await this.contract.assetsTokensAddresses();
}
}
11 changes: 5 additions & 6 deletions src/services/adapters/registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,16 @@ import { Context } from "../../context";
import { ZeroAddress } from "../../helpers";
import { structArray } from "../../struct";

import { Position, VaultStatic, VaultDynamic, ERC20 } from "../../types";
import { Position, VaultStatic, VaultDynamic } from "../../types";

export interface IRegistryAdapter {
assetsStatic(): Promise<VaultStatic[]>;
assetsDynamic(): Promise<VaultDynamic[]>;
positionsOf(address: Address, addresses?: Address[]): Promise<Position[]>;
tokens(): Promise<ERC20[]>;
tokens(): Promise<Address[]>;
}

const VaultV2MetadataAbi = `tuple(
string symbol,
uint256 pricePerShare,
bool migrationAvailable,
address latestVaultAddress,
Expand All @@ -27,7 +26,7 @@ export class RegistryV2Adapter<T extends ChainId> extends ContractService implem
static abi = AdapterAbi(VaultV2MetadataAbi);

constructor(chainId: T, ctx: Context) {
super(ctx.address("registryV2Adapter") ?? RegistryV2Adapter.addressByChain(chainId), chainId, ctx);
super(ctx.addresses.adapters.registryV2 ?? RegistryV2Adapter.addressByChain(chainId), chainId, ctx);
}

static addressByChain(chainId: ChainId): string {
Expand Down Expand Up @@ -71,7 +70,7 @@ export class RegistryV2Adapter<T extends ChainId> extends ContractService implem
return await this.contract["assetsPositionsOf(address)"](address).then(structArray);
}

async tokens(): Promise<ERC20[]> {
return await this.contract.tokens().then(structArray);
async tokens(): Promise<Address[]> {
return await this.contract.assetsTokensAddresses();
}
}
30 changes: 30 additions & 0 deletions src/services/helper.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { TokenAbi } from "../abi";
import { ChainId } from "../chain";
import { Address, ContractService } from "../common";
import { Context } from "../context";
import { structArray } from "../struct";

import { ERC20 } from "../types";

const HelperAbi = [`function tokensMetadata(address[] memory) public view returns (${TokenAbi}[] memory)`];

export class HelperService<T extends ChainId> extends ContractService {
static abi = HelperAbi;

constructor(chainId: T, ctx: Context) {
super(ctx.addresses.helper ?? HelperService.addressByChain(chainId), chainId, ctx);
}

static addressByChain(chainId: ChainId): string {
switch (chainId) {
case 1: // FIXME: doesn't actually exist
case 250: // ditto
case 1337: // ditto
return "0x420b1099B9eF5baba6D92029594eF45E19A04A4A";
}
}

async tokens(addresses: Address[]): Promise<ERC20[]> {
return await this.contract.tokensMetadata(addresses).then(structArray);
}
}
2 changes: 1 addition & 1 deletion src/services/lens.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class LensService<T extends ChainId> extends ContractService {
static abi = LensAbi;

constructor(chainId: T, ctx: Context) {
super(ctx.address("lens") ?? LensService.addressByChain(chainId), chainId, ctx);
super(ctx.addresses.lens ?? LensService.addressByChain(chainId), chainId, ctx);
}

get adapters(): Adapters<T> {
Expand Down
2 changes: 1 addition & 1 deletion src/services/oracle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class OracleService<T extends ChainId> extends ContractService {
static abi = OracleAbi;

constructor(chainId: T, ctx: Context) {
super(ctx.address("oracle") ?? OracleService.addressByChain(chainId), chainId, ctx);
super(ctx.addresses.oracle ?? OracleService.addressByChain(chainId), chainId, ctx);
}

static addressByChain(chainId: ChainId): string {
Expand Down
6 changes: 5 additions & 1 deletion src/yearn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { IconsService } from "./services/icons";
import { SubgraphService } from "./services/subgraph";
import { EarningsReader } from "./readers/earnings";
import { IronBankReader } from "./readers/ironbank";
import { HelperService } from "./services/helper";

export class Yearn<T extends ChainId> {
services: {
Expand All @@ -20,6 +21,8 @@ export class Yearn<T extends ChainId> {
icons: IconsService;
apy: ApyService;
subgraph: SubgraphService;

helper: HelperService<T>;
};

vaults: VaultReader<T>;
Expand All @@ -38,7 +41,8 @@ export class Yearn<T extends ChainId> {
zapper: new ZapperService(chainId, ctx),
icons: new IconsService(chainId, ctx),
apy: new ApyService(chainId, ctx),
subgraph: new SubgraphService(chainId, ctx)
subgraph: new SubgraphService(chainId, ctx),
helper: new HelperService(chainId, ctx)
};

this.vaults = new VaultReader(this, chainId, ctx);
Expand Down
Loading

0 comments on commit d5c7d64

Please sign in to comment.