diff --git a/src/apps/coslend/coslend.module.ts b/src/apps/coslend/coslend.module.ts index d92697c28..d7ac5bb79 100644 --- a/src/apps/coslend/coslend.module.ts +++ b/src/apps/coslend/coslend.module.ts @@ -6,7 +6,6 @@ import { CoslendAppDefinition, COSLEND_DEFINITION } from './coslend.definition'; import { EvmosCoslendBalanceFetcher } from './evmos/coslend.balance-fetcher'; import { EvmosCoslendBorrowContractPositionFetcher } from './evmos/coslend.borrow.contract-position-fetcher'; import { EvmosCoslendSupplyTokenFetcher } from './evmos/coslend.supply.token-fetcher'; -import { EvmosCoslendTvlFetcher } from './evmos/coslend.tvl-fetcher'; import { CoslendBorrowBalanceHelper } from './helper/coslend.borrow.balance-helper'; import { CoslendBorrowContractPositionHelper } from './helper/coslend.borrow.contract-position-helper'; import { CoslendLendingMetaHelper } from './helper/coslend.lending.meta-helper'; @@ -22,7 +21,6 @@ import { CoslendTvlHelper } from './helper/coslend.tvl-helper'; EvmosCoslendBalanceFetcher, EvmosCoslendBorrowContractPositionFetcher, EvmosCoslendSupplyTokenFetcher, - EvmosCoslendTvlFetcher, // Helpers CoslendLendingMetaHelper, CoslendSupplyTokenHelper, diff --git a/src/apps/coslend/evmos/coslend.borrow.contract-position-fetcher.ts b/src/apps/coslend/evmos/coslend.borrow.contract-position-fetcher.ts index 5d9e09633..7d14beb21 100644 --- a/src/apps/coslend/evmos/coslend.borrow.contract-position-fetcher.ts +++ b/src/apps/coslend/evmos/coslend.borrow.contract-position-fetcher.ts @@ -12,7 +12,7 @@ const appId = COSLEND_DEFINITION.id; const groupId = COSLEND_DEFINITION.groups.borrow.id; const network = Network.EVMOS_MAINNET; -@Register.ContractPositionFetcher({ appId, groupId, network }) +@Register.ContractPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EvmosCoslendBorrowContractPositionFetcher implements PositionFetcher { constructor( @Inject(CoslendBorrowContractPositionHelper) diff --git a/src/apps/coslend/evmos/coslend.supply.token-fetcher.ts b/src/apps/coslend/evmos/coslend.supply.token-fetcher.ts index ff50b49b6..4be4c5696 100644 --- a/src/apps/coslend/evmos/coslend.supply.token-fetcher.ts +++ b/src/apps/coslend/evmos/coslend.supply.token-fetcher.ts @@ -13,7 +13,7 @@ const appId = COSLEND_DEFINITION.id; const groupId = COSLEND_DEFINITION.groups.supply.id; const network = Network.EVMOS_MAINNET; -@Register.TokenPositionFetcher({ appId, groupId, network }) +@Register.TokenPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EvmosCoslendSupplyTokenFetcher implements PositionFetcher { constructor( @Inject(CoslendContractFactory) private readonly coslendContractFactory: CoslendContractFactory, @@ -25,7 +25,7 @@ export class EvmosCoslendSupplyTokenFetcher implements PositionFetcher this.coslendContractFactory.coslendComptroller({ address, network }), getTokenContract: ({ address, network }) => this.coslendContractFactory.coslendCToken({ address, network }), diff --git a/src/apps/coslend/evmos/coslend.tvl-fetcher.ts b/src/apps/coslend/evmos/coslend.tvl-fetcher.ts deleted file mode 100644 index 59c3dae32..000000000 --- a/src/apps/coslend/evmos/coslend.tvl-fetcher.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { Register } from '~app-toolkit/decorators'; -import { TvlFetcher } from '~stats/tvl/tvl-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { COSLEND_DEFINITION } from '../coslend.definition'; -import { CoslendTvlHelper } from '../helper/coslend.tvl-helper'; - -const appId = COSLEND_DEFINITION.id; -const network = Network.EVMOS_MAINNET; - -@Register.TvlFetcher({ appId, network }) -export class EvmosCoslendTvlFetcher implements TvlFetcher { - constructor(@Inject(CoslendTvlHelper) private readonly coslendTvlHelper: CoslendTvlHelper) {} - - async getTvl() { - const tvl = await this.coslendTvlHelper.getTotalSupplyBasedOnBorrowedPositions({ - appId, - groupIds: [COSLEND_DEFINITION.groups.borrow.id], - network, - }); - return tvl; - } -} diff --git a/src/apps/coslend/helper/coslend.borrow.contract-position-helper.ts b/src/apps/coslend/helper/coslend.borrow.contract-position-helper.ts index 3760aba40..81a641a05 100644 --- a/src/apps/coslend/helper/coslend.borrow.contract-position-helper.ts +++ b/src/apps/coslend/helper/coslend.borrow.contract-position-helper.ts @@ -77,7 +77,7 @@ export class CoslendBorrowContractPositionHelper { const borrowApy = appToken.dataProps.borrowApy; // Display Props - const label = `Borrowed ${getLabelFromToken(appToken.tokens[0])}`; + const label = `${getLabelFromToken(appToken.tokens[0])}`; const secondaryLabel = buildDollarDisplayItem(underlyingPrice); const tertiaryLabel = isNumber(borrowApy) ? `${(borrowApy * 100).toFixed(3)}% APR` : ''; const images = appToken.displayProps.images; diff --git a/src/apps/dfx/ethereum/dfx.curve.token-fetcher.ts b/src/apps/dfx/ethereum/dfx.curve.token-fetcher.ts index dd9930f70..f6dbe84cb 100644 --- a/src/apps/dfx/ethereum/dfx.curve.token-fetcher.ts +++ b/src/apps/dfx/ethereum/dfx.curve.token-fetcher.ts @@ -18,7 +18,7 @@ const appId = DFX_DEFINITION.id; const groupId = DFX_DEFINITION.groups.dfxCurve.id; const network = Network.ETHEREUM_MAINNET; -@Register.TokenPositionFetcher({ appId, groupId, network }) +@Register.TokenPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EthereumDfxCurveTokenFetcher implements PositionFetcher { constructor( @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, @@ -67,10 +67,10 @@ export class EthereumDfxCurveTokenFetcher implements PositionFetcher Number(reserveRaw) / 10 ** 18); // DFX report all token liquidity in 10**18 const pricePerShare = reserves.map(r => r / supply); - const price = totalLiquidity / supply; + const price = liquidity / supply; // Prepare display props const [, baseToken, quoteToken] = name.split('-'); @@ -92,7 +92,7 @@ export class EthereumDfxCurveTokenFetcher implements PositionFetcher { constructor( diff --git a/src/apps/ease/ease.module.ts b/src/apps/ease/ease.module.ts index e323de0fc..4560b4c99 100644 --- a/src/apps/ease/ease.module.ts +++ b/src/apps/ease/ease.module.ts @@ -5,16 +5,9 @@ import { EaseContractFactory } from './contracts'; import { EaseAppDefinition, EASE_DEFINITION } from './ease.definition'; import { EthereumEaseBalanceFetcher } from './ethereum/ease.balance-fetcher'; import { EthereumEaseRcaTokenFetcher } from './ethereum/ease.rca.token-fetcher'; -import { EthereumEaseTvlFetcher } from './ethereum/ease.tvl-fetcher'; @Register.AppModule({ appId: EASE_DEFINITION.id, - providers: [ - EaseAppDefinition, - EaseContractFactory, - EthereumEaseBalanceFetcher, - EthereumEaseRcaTokenFetcher, - EthereumEaseTvlFetcher, - ], + providers: [EaseAppDefinition, EaseContractFactory, EthereumEaseBalanceFetcher, EthereumEaseRcaTokenFetcher], }) export class EaseAppModule extends AbstractApp() {} diff --git a/src/apps/ease/ethereum/ease.balance-fetcher.ts b/src/apps/ease/ethereum/ease.balance-fetcher.ts index 05d2fd120..2ab23fe12 100644 --- a/src/apps/ease/ethereum/ease.balance-fetcher.ts +++ b/src/apps/ease/ethereum/ease.balance-fetcher.ts @@ -19,7 +19,7 @@ export class EthereumEaseBalanceFetcher implements BalanceFetcher { address, appId: EASE_DEFINITION.id, groupId: EASE_DEFINITION.groups.rca.id, - network: network, + network, }); } diff --git a/src/apps/ease/ethereum/ease.rca.token-fetcher.ts b/src/apps/ease/ethereum/ease.rca.token-fetcher.ts index 0c16920e0..d0391381c 100644 --- a/src/apps/ease/ethereum/ease.rca.token-fetcher.ts +++ b/src/apps/ease/ethereum/ease.rca.token-fetcher.ts @@ -4,6 +4,8 @@ import _ from 'lodash'; import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface'; import { Register } from '~app-toolkit/decorators'; +import { AAVE_V2_DEFINITION } from '~apps/aave-v2/aave-v2.definition'; +import { COMPOUND_DEFINITION } from '~apps/compound/compound.definition'; import { YEARN_DEFINITION } from '~apps/yearn/yearn.definition'; import { PositionFetcher } from '~position/position-fetcher.interface'; import { AppTokenPosition } from '~position/position.interface'; @@ -24,7 +26,7 @@ export type EaseRcaVaultDetails = { token: []; }; -@Register.TokenPositionFetcher({ appId, groupId, network }) +@Register.TokenPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EthereumEaseRcaTokenFetcher implements PositionFetcher { constructor( @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, @@ -36,16 +38,16 @@ export class EthereumEaseRcaTokenFetcher implements PositionFetcher(endpoint).then(v => v.data); const rcaAddressToDetails = _.keyBy(ethData, v => v.address.toLowerCase()); return this.appToolkit.helpers.vaultTokenHelper.getTokens({ - appId: EASE_DEFINITION.id, - groupId: EASE_DEFINITION.groups.rca.id, - network: Network.ETHEREUM_MAINNET, + appId, + groupId, + network, dependencies: [ { appId: YEARN_DEFINITION.id, groupIds: [YEARN_DEFINITION.groups.vault.id], network }, + { appId: AAVE_V2_DEFINITION.id, groupIds: [AAVE_V2_DEFINITION.groups.supply.id], network }, + { appId: COMPOUND_DEFINITION.id, groupIds: [COMPOUND_DEFINITION.groups.supply.id], network }, //TODO: migrate { appId: 'sushiswap', groupIds: ['pool'], network }, { appId: 'convex', groupIds: ['deposit'], network }, - { appId: 'aave-v2', groupIds: ['supply'], network }, - { appId: 'compound', groupIds: ['supply'], network }, ], resolveContract: ({ address, network }) => this.easeContractFactory.easeRcaShield({ address, network }), resolveVaultAddresses: async () => ethData.map(({ address }) => address.toLowerCase()), diff --git a/src/apps/ease/ethereum/ease.tvl-fetcher.ts b/src/apps/ease/ethereum/ease.tvl-fetcher.ts deleted file mode 100644 index 85aa58661..000000000 --- a/src/apps/ease/ethereum/ease.tvl-fetcher.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { Inject } from '@nestjs/common'; -import { sumBy } from 'lodash'; - -import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface'; -import { Register } from '~app-toolkit/decorators'; -import { TvlFetcher } from '~stats/tvl/tvl-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { EASE_DEFINITION } from '../ease.definition'; - -const appId = EASE_DEFINITION.id; -const network = Network.ETHEREUM_MAINNET; - -@Register.TvlFetcher({ appId, network }) -export class EthereumEaseTvlFetcher implements TvlFetcher { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getTvl() { - const tokens = await this.appToolkit.getAppTokenPositions({ - appId, - groupIds: [EASE_DEFINITION.groups.rca.id], - network, - }); - return sumBy(tokens, v => v.supply * v.price); - } -} diff --git a/src/apps/enzyme-finance/ethereum/enzyme-finance.vault.token-fetcher.ts b/src/apps/enzyme-finance/ethereum/enzyme-finance.vault.token-fetcher.ts index 960bcbdc9..cc93af995 100644 --- a/src/apps/enzyme-finance/ethereum/enzyme-finance.vault.token-fetcher.ts +++ b/src/apps/enzyme-finance/ethereum/enzyme-finance.vault.token-fetcher.ts @@ -33,7 +33,7 @@ const appId = ENZYME_FINANCE_DEFINITION.id; const groupId = ENZYME_FINANCE_DEFINITION.groups.vault.id; const network = Network.ETHEREUM_MAINNET; -@Register.TokenPositionFetcher({ appId, groupId, network }) +@Register.TokenPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EthereumEnzymeFinanceVaultTokenFetcher implements PositionFetcher { constructor( @Inject(EnzymeFinanceContractFactory) private readonly enzymeFinanceContractFactory: EnzymeFinanceContractFactory, diff --git a/src/apps/euler/ethereum/euler.balance-fetcher.ts b/src/apps/euler/ethereum/euler.balance-fetcher.ts index c4cd90638..26bc52000 100644 --- a/src/apps/euler/ethereum/euler.balance-fetcher.ts +++ b/src/apps/euler/ethereum/euler.balance-fetcher.ts @@ -19,7 +19,7 @@ export class EthereumEulerBalanceFetcher implements BalanceFetcher { address, appId: EULER_DEFINITION.id, groupId: EULER_DEFINITION.groups.eToken.id, - network: network, + network, }); } @@ -28,7 +28,7 @@ export class EthereumEulerBalanceFetcher implements BalanceFetcher { address, appId: EULER_DEFINITION.id, groupId: EULER_DEFINITION.groups.dToken.id, - network: network, + network, }); } @@ -37,7 +37,7 @@ export class EthereumEulerBalanceFetcher implements BalanceFetcher { address, appId: EULER_DEFINITION.id, groupId: EULER_DEFINITION.groups.pToken.id, - network: network, + network, }); } diff --git a/src/apps/euler/ethereum/euler.d-token.token-fetcher.ts b/src/apps/euler/ethereum/euler.d-token.token-fetcher.ts index e1d911d94..d226b7833 100644 --- a/src/apps/euler/ethereum/euler.d-token.token-fetcher.ts +++ b/src/apps/euler/ethereum/euler.d-token.token-fetcher.ts @@ -57,7 +57,14 @@ interface EulerMarketsResponse { }; } -@Register.TokenPositionFetcher({ appId, groupId, network }) +type EulerTokenDataProps = { + liquidity: number; + interestRate: number; + borrowAPY: number; + supplyAPY: number; +}; + +@Register.TokenPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EthereumEulerDTokenTokenFetcher implements PositionFetcher { constructor( @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, @@ -67,6 +74,7 @@ export class EthereumEulerDTokenTokenFetcher implements PositionFetcher({ endpoint, query }); + const multicall = this.appToolkit.getMulticall(network); const baseTokens = await this.appToolkit.getBaseTokenPrices(network); const tokens = await Promise.all( @@ -78,53 +86,68 @@ export class EthereumEulerDTokenTokenFetcher implements PositionFetcher token?.address === market.id.toLowerCase()); + if (totalSupplyRaw.isZero() || !underlyingToken) return null; - if (totalSupply.isZero() || !underlyingToken) return null; + const supply = Number(totalSupplyRaw) / 10 ** decimals; + const symbol = `D${market.symbol}`; + const price = underlyingToken.price; + const pricePerShare = 1; + const liquidity = supply * underlyingToken.price * -1; + const interestRate = Number(market.interestRate) / 10 ** decimals; + const borrowAPY = Number(market.borrowAPY) / 10 ** 25; + const supplyAPY = Number(market.supplyAPY) / 10 ** 25; const dataProps = { - name: `Euler D token ${market.name}`, - liquidity: Number(totalSupply) * underlyingToken.price, - interestRate: Number(market.interestRate) / 10 ** 18, - borrowAPY: Number(market.borrowAPY) / 10 ** 18, - supplyAPY: Number(market.borrowAPY) / 10 ** 18, + liquidity, + interestRate, + borrowAPY, + supplyAPY, + }; + + const statsItems = [ + { + label: 'Liquidity', + value: buildDollarDisplayItem(liquidity), + }, + { + label: 'Borrow APY', + value: buildDollarDisplayItem(borrowAPY), + }, + { + label: 'Supply APY', + value: buildDollarDisplayItem(supplyAPY), + }, + ]; + + const displayProps = { + label: `Euler D token ${market.name}`, + secondaryLabel: buildDollarDisplayItem(price), + images: getImagesFromToken(underlyingToken), + statsItems, }; - return { + const token: AppTokenPosition = { + type: ContractType.APP_TOKEN, address: market.dTokenAddress, - symbol: `D${market.symbol}`, - name: `Euler D token ${market.name}`, - type: ContractType.APP_TOKEN as const, - supply: Number(market.totalSupply) / 10 ** Number(market.decimals), - pricePerShare: 1, - price: underlyingToken.price, + appId, + groupId, network, - decimals: 18, + symbol, + decimals, + supply, + price, + pricePerShare, tokens: [underlyingToken], dataProps, - displayProps: { - label: `Euler D token ${market.name}`, - secondaryLabel: buildDollarDisplayItem(underlyingToken.price), - images: getImagesFromToken(underlyingToken), - statsItems: [ - { - label: 'Liquidity', - value: buildDollarDisplayItem(dataProps.liquidity), - }, - { - label: 'Borrow APY', - value: buildDollarDisplayItem(dataProps.borrowAPY), - }, - { - label: 'Supply APY', - value: buildDollarDisplayItem(dataProps.supplyAPY), - }, - ], - }, - appId, - groupId, + displayProps, }; + + return token; }), ); diff --git a/src/apps/euler/ethereum/euler.e-token.token-fetcher.ts b/src/apps/euler/ethereum/euler.e-token.token-fetcher.ts index d5e07fd33..3959a4bfe 100644 --- a/src/apps/euler/ethereum/euler.e-token.token-fetcher.ts +++ b/src/apps/euler/ethereum/euler.e-token.token-fetcher.ts @@ -59,7 +59,14 @@ interface EulerMarketsResponse { }; } -@Register.TokenPositionFetcher({ appId, groupId, network }) +type EulerTokenDataProps = { + liquidity: number; + interestRate: number; + borrowAPY: number; + supplyAPY: number; +}; + +@Register.TokenPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EthereumEulerETokenTokenFetcher implements PositionFetcher { constructor( @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, @@ -69,6 +76,7 @@ export class EthereumEulerETokenTokenFetcher implements PositionFetcher({ endpoint, query }); + const multicall = this.appToolkit.getMulticall(network); const baseTokens = await this.appToolkit.getBaseTokenPrices(network); const tokens = await Promise.all( @@ -80,58 +88,68 @@ export class EthereumEulerETokenTokenFetcher implements PositionFetcher token?.address === market.id.toLowerCase()); + const [totalSupplyRaw, decimals] = await Promise.all([ + multicall.wrap(eTokenContract).totalSupply(), + multicall.wrap(eTokenContract).decimals(), + ]); + const underlyingToken = baseTokens.find(token => token.address === market.id.toLowerCase()); + if (totalSupplyRaw.isZero() || !underlyingToken) return null; + + const supply = Number(totalSupplyRaw) / 10 ** decimals; + const symbol = `E${market.symbol}`; + const price = underlyingToken.price; + const pricePerShare = Number(supply) / Number(market.totalBalances); + const liquidity = supply * underlyingToken.price; + const interestRate = Number(market.interestRate) / 10 ** decimals; + const borrowAPY = Number(market.borrowAPY) / 10 ** 25; + const supplyAPY = Number(market.supplyAPY) / 10 ** 25; - if (totalSupply.isZero() || !underlyingToken) return null; + const dataProps = { + liquidity, + interestRate, + borrowAPY, + supplyAPY, + }; - const pricePerShare = Number(totalSupply.toString()) / Number(market.totalBalances); + const statsItems = [ + { + label: 'Liquidity', + value: buildDollarDisplayItem(dataProps.liquidity), + }, + { + label: 'Borrow APY', + value: buildDollarDisplayItem(dataProps.borrowAPY), + }, + { + label: 'Supply APY', + value: buildDollarDisplayItem(dataProps.supplyAPY), + }, + ]; - const dataProps = { - name: `Euler E token ${market.name}`, - liquidity: Number(totalSupply) * underlyingToken.price, - underlyingAddress: market.id, - interestRate: Number(market.interestRate) / 10 ** 18, - borrowAPY: Number(market.borrowAPY) / 10 ** 18, - supplyAPY: Number(market.borrowAPY) / 10 ** 18, - totalSupply: totalSupply.toString(), - totalBalances: market.totalBalances, + const displayProps = { + label: `Euler E token ${market.name}`, + secondaryLabel: buildDollarDisplayItem(price), + images: getImagesFromToken(underlyingToken), + statsItems, }; - return { + const token: AppTokenPosition = { + type: ContractType.APP_TOKEN, address: market.eTokenAddress, - symbol: `E${market.symbol}`, - name: `Euler E token ${market.name}`, - type: ContractType.APP_TOKEN as const, - supply: Number(market.totalSupply) / 10 ** Number(market.decimals), - pricePerShare, - price: underlyingToken.price, + appId, + groupId, network, - decimals: 18, + symbol, + decimals, + supply, + price, + pricePerShare, tokens: [underlyingToken], dataProps, - displayProps: { - label: `Euler E token ${market.name}`, - secondaryLabel: buildDollarDisplayItem(pricePerShare), - images: getImagesFromToken(underlyingToken), - statsItems: [ - { - label: 'Liquidity', - value: buildDollarDisplayItem(dataProps.liquidity), - }, - { - label: 'Borrow APY', - value: buildDollarDisplayItem(dataProps.borrowAPY), - }, - { - label: 'Supply APY', - value: buildDollarDisplayItem(dataProps.supplyAPY), - }, - ], - }, - appId, - groupId, + displayProps, }; + + return token; }), ); diff --git a/src/apps/euler/ethereum/euler.p-token.token-fetcher.ts b/src/apps/euler/ethereum/euler.p-token.token-fetcher.ts index aa36b5cab..e3b98e4c1 100644 --- a/src/apps/euler/ethereum/euler.p-token.token-fetcher.ts +++ b/src/apps/euler/ethereum/euler.p-token.token-fetcher.ts @@ -57,7 +57,14 @@ interface EulerMarketsResponse { }; } -@Register.TokenPositionFetcher({ appId, groupId, network }) +type EulerTokenDataProps = { + liquidity: number; + interestRate: number; + borrowAPY: number; + supplyAPY: number; +}; + +@Register.TokenPositionFetcher({ appId, groupId, network, options: { includeInTvl: true } }) export class EthereumEulerPTokenTokenFetcher implements PositionFetcher { constructor( @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, @@ -67,64 +74,79 @@ export class EthereumEulerPTokenTokenFetcher implements PositionFetcher({ endpoint, query }); + const multicall = this.appToolkit.getMulticall(network); const baseTokens = await this.appToolkit.getBaseTokenPrices(network); const tokens = await Promise.all( data.eulerMarketStore.markets.map(async market => { if (market.pTokenAddress === ZERO_ADDRESS) return null; - const pTokenContract = this.eulerContractFactory.eulerPtokenContract({ address: market.pTokenAddress, network, }); - const totalSupply = await pTokenContract.totalSupply(); + const [totalSupplyRaw, decimals] = await Promise.all([ + multicall.wrap(pTokenContract).totalSupply(), + multicall.wrap(pTokenContract).decimals(), + ]); const underlyingToken = baseTokens.find(token => token?.address === market.id.toLowerCase()); + if (totalSupplyRaw.isZero() || !underlyingToken) return null; - if (totalSupply.isZero() || !underlyingToken) return null; + const supply = Number(totalSupplyRaw) / 10 ** decimals; + const symbol = `P${market.symbol}`; + const price = underlyingToken.price; + const pricePerShare = 1; + const liquidity = supply * underlyingToken.price; + const interestRate = Number(market.interestRate) / 10 ** decimals; + const borrowAPY = Number(market.borrowAPY) / 10 ** 25; + const supplyAPY = Number(market.supplyAPY) / 10 ** 25; const dataProps = { - name: market.name, - liquidity: Number(totalSupply) * underlyingToken.price, - interestRate: Number(market.interestRate) / 10 ** 18, - borrowAPY: Number(market.borrowAPY) / 10 ** 18, - supplyAPY: Number(market.borrowAPY) / 10 ** 18, + liquidity, + interestRate, + borrowAPY, + supplyAPY, + }; + + const statsItems = [ + { + label: 'Liquidity', + value: buildDollarDisplayItem(dataProps.liquidity), + }, + { + label: 'Borrow APY', + value: buildDollarDisplayItem(dataProps.borrowAPY), + }, + { + label: 'Supply APY', + value: buildDollarDisplayItem(dataProps.supplyAPY), + }, + ]; + + const displayProps = { + label: `Euler P token ${market.name}`, + secondaryLabel: buildDollarDisplayItem(price), + images: getImagesFromToken(underlyingToken), + statsItems, }; - return { + const token: AppTokenPosition = { + type: ContractType.APP_TOKEN, address: market.pTokenAddress, - symbol: `P${market.symbol}`, - name: `Euler P token ${market.name}`, - type: ContractType.APP_TOKEN as const, - supply: Number(market.totalSupply) / 10 ** Number(market.decimals), - pricePerShare: 1, - price: underlyingToken.price, + appId, + groupId, network, - decimals: 18, + symbol, + decimals, + supply, + price, + pricePerShare, tokens: [underlyingToken], dataProps, - displayProps: { - label: `Euler P token ${market.name}`, - secondaryLabel: buildDollarDisplayItem(underlyingToken.price), - images: getImagesFromToken(underlyingToken), - statsItems: [ - { - label: 'Liquidity', - value: buildDollarDisplayItem(dataProps.liquidity), - }, - { - label: 'Borrow APY', - value: buildDollarDisplayItem(dataProps.borrowAPY), - }, - { - label: 'Supply APY', - value: buildDollarDisplayItem(dataProps.supplyAPY), - }, - ], - }, - appId, - groupId, + displayProps, }; + + return token; }), ); diff --git a/src/apps/euler/ethereum/euler.tvl-fetcher.ts b/src/apps/euler/ethereum/euler.tvl-fetcher.ts deleted file mode 100644 index d9074a6e4..000000000 --- a/src/apps/euler/ethereum/euler.tvl-fetcher.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Inject } from '@nestjs/common'; -import { gql } from 'graphql-request'; -import { sum } from 'lodash'; - -import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface'; -import { Register } from '~app-toolkit/decorators'; -import { TvlFetcher } from '~stats/tvl/tvl-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { EULER_DEFINITION } from '../euler.definition'; - -const appId = EULER_DEFINITION.id; -const network = Network.ETHEREUM_MAINNET; - -interface EulerMarket { - symbol: string; - totalBalances: string; - totalBorrows: string; -} - -interface EulerMarketsResponse { - eulerMarketStore: { - markets: EulerMarket[]; - }; -} - -const query = gql` - { - eulerMarketStore(id: "euler-market-store") { - markets { - symbol - totalBalances - totalBorrows - } - } - } -`; - -@Register.TvlFetcher({ appId, network }) -export class EthereumEulerTvlFetcher implements TvlFetcher { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getTvl() { - const prices = await this.appToolkit.getBaseTokenPrices(network); - const endpoint = 'https://api.thegraph.com/subgraphs/name/euler-xyz/euler-mainnet'; - const data = await this.appToolkit.helpers.theGraphHelper.request({ endpoint, query }); - const markets = data.eulerMarketStore.markets; - - const tvlPerMarket = markets.map(market => { - const baseToken = prices.find(x => x.symbol === market.symbol); - if (!baseToken) return 0; - - const totalBalance = Number(market.totalBalances) / 10 ** 18; - const totalBorrows = Number(market.totalBorrows) / 10 ** 18; - - return (totalBalance - totalBorrows) * baseToken.price; - }); - - return sum(tvlPerMarket); - } -} diff --git a/src/apps/euler/euler.definition.ts b/src/apps/euler/euler.definition.ts index 734a3891e..a197cba7d 100644 --- a/src/apps/euler/euler.definition.ts +++ b/src/apps/euler/euler.definition.ts @@ -32,7 +32,10 @@ export const EULER_DEFINITION = appDefinition({ tags: [AppTag.LENDING], keywords: [], - links: {}, + links: { + twitter: 'https://twitter.com/eulerfinance', + discord: 'https://discord.com/invite/CdG97VSYGk', + }, supportedNetworks: { [Network.ETHEREUM_MAINNET]: [AppAction.VIEW], diff --git a/src/apps/euler/euler.module.ts b/src/apps/euler/euler.module.ts index 2073e22f1..eb43c8a61 100644 --- a/src/apps/euler/euler.module.ts +++ b/src/apps/euler/euler.module.ts @@ -6,7 +6,6 @@ import { EthereumEulerBalanceFetcher } from './ethereum/euler.balance-fetcher'; import { EthereumEulerDTokenTokenFetcher } from './ethereum/euler.d-token.token-fetcher'; import { EthereumEulerETokenTokenFetcher } from './ethereum/euler.e-token.token-fetcher'; import { EthereumEulerPTokenTokenFetcher } from './ethereum/euler.p-token.token-fetcher'; -import { EthereumEulerTvlFetcher } from './ethereum/euler.tvl-fetcher'; import { EulerAppDefinition, EULER_DEFINITION } from './euler.definition'; @Register.AppModule({ @@ -16,7 +15,6 @@ import { EulerAppDefinition, EULER_DEFINITION } from './euler.definition'; EthereumEulerDTokenTokenFetcher, EthereumEulerETokenTokenFetcher, EthereumEulerPTokenTokenFetcher, - EthereumEulerTvlFetcher, EulerAppDefinition, EulerContractFactory, ], diff --git a/src/apps/good-ghosting/polygon/good-ghosting.game.contract-position-fetcher.ts b/src/apps/good-ghosting/polygon/good-ghosting.game.contract-position-fetcher.ts index 87c3edd19..5b5609723 100644 --- a/src/apps/good-ghosting/polygon/good-ghosting.game.contract-position-fetcher.ts +++ b/src/apps/good-ghosting/polygon/good-ghosting.game.contract-position-fetcher.ts @@ -1,12 +1,10 @@ import { Inject } from '@nestjs/common'; -import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface'; import { Register } from '~app-toolkit/decorators'; import { PositionFetcher } from '~position/position-fetcher.interface'; import { ContractPosition } from '~position/position.interface'; import { Network } from '~types/network.interface'; -import { GoodGhostingContractFactory } from '../contracts'; import { GOOD_GHOSTING_DEFINITION } from '../good-ghosting.definition'; import { NetworkId } from '../helpers/constants'; import { GoodGhostingGameContractPositionFetcherHelper } from '../helpers/good-ghosting.game.contract-position-fetcher-helper'; @@ -19,9 +17,6 @@ const networkId = NetworkId.PolygonMainnet; @Register.ContractPositionFetcher({ appId, groupId, network }) export class PolygonGoodGhostingGameContractPositionFetcher implements PositionFetcher { constructor( - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - @Inject(GoodGhostingContractFactory) private readonly goodGhostingContractFactory: GoodGhostingContractFactory, - @Inject(GoodGhostingGameContractPositionFetcherHelper) private readonly helper: GoodGhostingGameContractPositionFetcherHelper, ) {} diff --git a/src/apps/gro/avalanche/gro.balance-fetcher.ts b/src/apps/gro/avalanche/gro.balance-fetcher.ts index 01fdd562c..209c276e0 100644 --- a/src/apps/gro/avalanche/gro.balance-fetcher.ts +++ b/src/apps/gro/avalanche/gro.balance-fetcher.ts @@ -19,7 +19,7 @@ export class AvalancheGroBalanceFetcher implements BalanceFetcher { address, appId: GRO_DEFINITION.id, groupId: GRO_DEFINITION.groups.labs.id, - network: Network.AVALANCHE_MAINNET, + network, }); } diff --git a/src/apps/gro/avalanche/gro.labs.token-fetcher.ts b/src/apps/gro/avalanche/gro.labs.token-fetcher.ts index 84eb519ed..9913cbe02 100644 --- a/src/apps/gro/avalanche/gro.labs.token-fetcher.ts +++ b/src/apps/gro/avalanche/gro.labs.token-fetcher.ts @@ -25,9 +25,9 @@ export class AvalancheGroLabsTokenFetcher implements PositionFetcher { - const groVestingAddress = '0x748218256AfE0A19a88EBEB2E0C5Ce86d2178360'; + const groVestingAddress = '0x748218256afe0a19a88ebeb2e0c5ce86d2178360'; const contract = this.groContractFactory.groVesting({ network, address: groVestingAddress.toLowerCase() }); const lockedToken = contractPosition.tokens.find(isLocked)!; const unlockedToken = contractPosition.tokens.find(isClaimable)!; diff --git a/src/apps/gro/ethereum/gro.farm.contract-position-fetcher.ts b/src/apps/gro/ethereum/gro.farm.contract-position-fetcher.ts index cc346172c..424d39fba 100644 --- a/src/apps/gro/ethereum/gro.farm.contract-position-fetcher.ts +++ b/src/apps/gro/ethereum/gro.farm.contract-position-fetcher.ts @@ -25,7 +25,7 @@ export class EthereumGroFarmContractPositionFetcher implements PositionFetcher[]> { return this.appToolkit.helpers.masterChefContractPositionHelper.getContractPositions({ - address: '0x2E32bAd45a1C29c1EA27cf4dD588DF9e68ED376C'.toLowerCase(), + address: '0x2e32bad45a1c29c1ea27cf4dd588df9e68ed376c'.toLowerCase(), appId, groupId, network, diff --git a/src/apps/gro/ethereum/gro.vesting.contract-position-fetcher.ts b/src/apps/gro/ethereum/gro.vesting.contract-position-fetcher.ts index 7cefe8912..5137e3f42 100644 --- a/src/apps/gro/ethereum/gro.vesting.contract-position-fetcher.ts +++ b/src/apps/gro/ethereum/gro.vesting.contract-position-fetcher.ts @@ -8,7 +8,6 @@ import { ContractPosition } from '~position/position.interface'; import { claimable, locked } from '~position/position.utils'; import { Network } from '~types/network.interface'; -import { GroContractFactory } from '../contracts'; import { GRO_DEFINITION } from '../gro.definition'; const appId = GRO_DEFINITION.id; @@ -17,14 +16,11 @@ const network = Network.ETHEREUM_MAINNET; @Register.ContractPositionFetcher({ appId, groupId, network }) export class EthereumGroVestingContractPositionFetcher implements PositionFetcher { - constructor( - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - @Inject(GroContractFactory) private readonly groContractFactory: GroContractFactory, - ) {} + constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} async getPositions() { - const groVestingAddress = '0x748218256AfE0A19a88EBEB2E0C5Ce86d2178360'; - const groDaoToken = '0x3Ec8798B81485A254928B70CDA1cf0A2BB0B74D7'; + const groVestingAddress = '0x748218256afe0a19a88ebeb2e0c5ce86d2178360'; + const groDaoToken = '0x3ec8798b81485a254928b70cda1cf0a2bb0b74d7'; const baseTokens = await this.appToolkit.getBaseTokenPrices(network); const underlyingToken = baseTokens.find(v => v.address === groDaoToken.toLowerCase()); const tokens = [locked(underlyingToken!), claimable(underlyingToken!)]; diff --git a/src/apps/impermax/arbitrum/impermax.collateral.token-fetcher.ts b/src/apps/impermax/arbitrum/impermax.collateral.token-fetcher.ts index 2a40dbac9..8e1b87418 100644 --- a/src/apps/impermax/arbitrum/impermax.collateral.token-fetcher.ts +++ b/src/apps/impermax/arbitrum/impermax.collateral.token-fetcher.ts @@ -8,12 +8,12 @@ import { Network } from '~types/network.interface'; import { ImpermaxCollateralTokenHelper } from '../helpers/impermax.collateral.token-fetcher-helper'; import { IMPERMAX_DEFINITION } from '../impermax.definition'; -import { address } from './impermax.lend.token-fetcher'; - const appId = IMPERMAX_DEFINITION.id; const groupId = IMPERMAX_DEFINITION.groups.collateral.id; const network = Network.ARBITRUM_MAINNET; +const address = '0x8c3736e2fe63cc2cd89ee228d9dbcab6ce5b767b'; + @Register.TokenPositionFetcher({ appId, groupId, network }) export class ArbitrumImpermaxCollateralTokenFetcher implements PositionFetcher { constructor( diff --git a/src/apps/impermax/arbitrum/impermax.lend.token-fetcher.ts b/src/apps/impermax/arbitrum/impermax.lend.token-fetcher.ts index 5f7832050..0b3b57e93 100644 --- a/src/apps/impermax/arbitrum/impermax.lend.token-fetcher.ts +++ b/src/apps/impermax/arbitrum/impermax.lend.token-fetcher.ts @@ -11,7 +11,8 @@ import { IMPERMAX_DEFINITION } from '../impermax.definition'; const appId = IMPERMAX_DEFINITION.id; const groupId = IMPERMAX_DEFINITION.groups.lend.id; const network = Network.ARBITRUM_MAINNET; -export const address = '0x8C3736e2FE63cc2cD89Ee228D9dBcAb6CE5B767B'.toLowerCase(); + +const address = '0x8c3736e2fe63cc2cd89ee228d9dbcab6ce5b767b'; @Register.TokenPositionFetcher({ appId, groupId, network }) export class ArbitrumImpermaxLendTokenFetcher implements PositionFetcher { diff --git a/src/apps/impermax/ethereum/impermax.collateral.token-fetcher.ts b/src/apps/impermax/ethereum/impermax.collateral.token-fetcher.ts index 2392c08c9..343efa909 100644 --- a/src/apps/impermax/ethereum/impermax.collateral.token-fetcher.ts +++ b/src/apps/impermax/ethereum/impermax.collateral.token-fetcher.ts @@ -9,12 +9,12 @@ import { Network } from '~types/network.interface'; import { ImpermaxCollateralTokenHelper } from '../helpers/impermax.collateral.token-fetcher-helper'; import { IMPERMAX_DEFINITION } from '../impermax.definition'; -import { address } from './impermax.lend.token-fetcher'; - const appId = IMPERMAX_DEFINITION.id; const groupId = IMPERMAX_DEFINITION.groups.collateral.id; const network = Network.ETHEREUM_MAINNET; +const address = '0x8c3736e2fe63cc2cd89ee228d9dbcab6ce5b767b'; + @Register.TokenPositionFetcher({ appId, groupId, network }) export class EthereumImpermaxCollateralTokenFetcher implements PositionFetcher { constructor( diff --git a/src/apps/impermax/ethereum/impermax.lend.token-fetcher.ts b/src/apps/impermax/ethereum/impermax.lend.token-fetcher.ts index a10b5ebcc..f79ca1673 100644 --- a/src/apps/impermax/ethereum/impermax.lend.token-fetcher.ts +++ b/src/apps/impermax/ethereum/impermax.lend.token-fetcher.ts @@ -11,7 +11,8 @@ import { IMPERMAX_DEFINITION } from '../impermax.definition'; const appId = IMPERMAX_DEFINITION.id; const groupId = IMPERMAX_DEFINITION.groups.lend.id; const network = Network.ETHEREUM_MAINNET; -export const address = '0x8C3736e2FE63cc2cD89Ee228D9dBcAb6CE5B767B'.toLowerCase(); + +export const address = '0x8c3736e2fe63cc2cd89ee228d9dbcab6ce5b767b'; @Register.TokenPositionFetcher({ appId, groupId, network }) export class EthereumImpermaxLendTokenFetcher implements PositionFetcher { diff --git a/src/apps/impermax/polygon/impermax.collateral.token-fetcher.ts b/src/apps/impermax/polygon/impermax.collateral.token-fetcher.ts index 4309e230a..b546750bc 100644 --- a/src/apps/impermax/polygon/impermax.collateral.token-fetcher.ts +++ b/src/apps/impermax/polygon/impermax.collateral.token-fetcher.ts @@ -8,12 +8,12 @@ import { Network } from '~types/network.interface'; import { ImpermaxCollateralTokenHelper } from '../helpers/impermax.collateral.token-fetcher-helper'; import { IMPERMAX_DEFINITION } from '../impermax.definition'; -import { address } from './impermax.lend.token-fetcher'; - const appId = IMPERMAX_DEFINITION.id; const groupId = IMPERMAX_DEFINITION.groups.collateral.id; const network = Network.POLYGON_MAINNET; +const address = '0x8c3736e2fe63cc2cd89ee228d9dbcab6ce5b767b'; + @Register.TokenPositionFetcher({ appId, groupId, network }) export class PolygonImpermaxCollateralTokenFetcher implements PositionFetcher { constructor( diff --git a/src/apps/impermax/polygon/impermax.lend.token-fetcher.ts b/src/apps/impermax/polygon/impermax.lend.token-fetcher.ts index 139496b4a..39f963c86 100644 --- a/src/apps/impermax/polygon/impermax.lend.token-fetcher.ts +++ b/src/apps/impermax/polygon/impermax.lend.token-fetcher.ts @@ -11,7 +11,8 @@ import { IMPERMAX_DEFINITION } from '../impermax.definition'; const appId = IMPERMAX_DEFINITION.id; const groupId = IMPERMAX_DEFINITION.groups.lend.id; const network = Network.POLYGON_MAINNET; -export const address = '0xBB92270716C8c424849F17cCc12F4F24AD4064D6'.toLowerCase(); + +export const address = '0xbb92270716c8c424849f17ccc12f4f24ad4064d6'; @Register.TokenPositionFetcher({ appId, groupId, network }) export class PolygonImpermaxLendTokenFetcher implements PositionFetcher {