diff --git a/src/apps/aave-amm/aave-amm.module.ts b/src/apps/aave-amm/aave-amm.module.ts index 5e94f9442..60f714dfb 100644 --- a/src/apps/aave-amm/aave-amm.module.ts +++ b/src/apps/aave-amm/aave-amm.module.ts @@ -20,6 +20,5 @@ import { EthereumAaveAmmVariableDebtTokenFetcher } from './ethereum/aave-amm.var EthereumAaveAmmSupplyTokenFetcher, EthereumAaveAmmVariableDebtTokenFetcher, ], - exports: [AaveAmmAppDefinition, AaveAmmContractFactory], }) export class AaveAmmAppModule extends AbstractApp() {} diff --git a/src/apps/aave-amm/ethereum/aave-amm.stable-debt.token-fetcher.ts b/src/apps/aave-amm/ethereum/aave-amm.stable-debt.token-fetcher.ts index 931252699..f1c058cd4 100644 --- a/src/apps/aave-amm/ethereum/aave-amm.stable-debt.token-fetcher.ts +++ b/src/apps/aave-amm/ethereum/aave-amm.stable-debt.token-fetcher.ts @@ -3,7 +3,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; import { AaveAmmAToken } from '../contracts'; diff --git a/src/apps/aave-amm/ethereum/aave-amm.supply.token-fetcher.ts b/src/apps/aave-amm/ethereum/aave-amm.supply.token-fetcher.ts index efcf39081..b793c4e24 100644 --- a/src/apps/aave-amm/ethereum/aave-amm.supply.token-fetcher.ts +++ b/src/apps/aave-amm/ethereum/aave-amm.supply.token-fetcher.ts @@ -3,7 +3,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; import { AaveAmmAToken } from '../contracts'; diff --git a/src/apps/aave-amm/ethereum/aave-amm.variable-debt.token-fetcher.ts b/src/apps/aave-amm/ethereum/aave-amm.variable-debt.token-fetcher.ts index 8a75f19f0..ab6392721 100644 --- a/src/apps/aave-amm/ethereum/aave-amm.variable-debt.token-fetcher.ts +++ b/src/apps/aave-amm/ethereum/aave-amm.variable-debt.token-fetcher.ts @@ -3,7 +3,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; import { AaveAmmAToken } from '../contracts'; diff --git a/src/apps/aave-amm/helpers/aave-amm.lending.template.token-fetcher.ts b/src/apps/aave-amm/helpers/aave-amm.lending.template.token-fetcher.ts index c467c37ef..dbe3884ce 100644 --- a/src/apps/aave-amm/helpers/aave-amm.lending.template.token-fetcher.ts +++ b/src/apps/aave-amm/helpers/aave-amm.lending.template.token-fetcher.ts @@ -6,7 +6,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { AppTokenTemplatePositionFetcher } from '~position/template/app-token.template.position-fetcher'; import { GetDataPropsParams, diff --git a/src/apps/aave-v2/aave-v2.module.ts b/src/apps/aave-v2/aave-v2.module.ts index bdd4a10b4..5c29b7b5e 100644 --- a/src/apps/aave-v2/aave-v2.module.ts +++ b/src/apps/aave-v2/aave-v2.module.ts @@ -14,8 +14,6 @@ import { EthereumAaveV2PositionPresenter } from './ethereum/aave-v2.position-pre import { EthereumAaveV2StableDebtTokenFetcher } from './ethereum/aave-v2.stable-debt.token-fetcher'; import { EthereumAaveV2SupplyTokenFetcher } from './ethereum/aave-v2.supply.token-fetcher'; import { EthereumAaveV2VariableDebtTokenFetcher } from './ethereum/aave-v2.variable-debt.token-fetcher'; -import { AaveV2ClaimableBalanceHelper } from './helpers/aave-v2.claimable.balance-helper'; -import { AaveV2ClaimableContractPositionHelper } from './helpers/aave-v2.claimable.contract-position-helper'; import { PolygonAaveV2ClaimableContractPositionFetcher } from './polygon/aave-v2.claimable.contract-position-fetcher'; import { PolygonAaveV2PositionPresenter } from './polygon/aave-v2.position-presenter'; import { PolygonAaveV2StableDebtTokenFetcher } from './polygon/aave-v2.stable-debt.token-fetcher'; @@ -25,8 +23,6 @@ import { PolygonAaveV2VariableDebtTokenFetcher } from './polygon/aave-v2.variabl @Module({ providers: [ AaveV2AppDefinition, - AaveV2ClaimableBalanceHelper, - AaveV2ClaimableContractPositionHelper, AaveV2ContractFactory, AvalancheAaveV2ClaimableContractPositionFetcher, AvalancheAaveV2PositionPresenter, @@ -44,6 +40,5 @@ import { PolygonAaveV2VariableDebtTokenFetcher } from './polygon/aave-v2.variabl PolygonAaveV2SupplyTokenFetcher, PolygonAaveV2VariableDebtTokenFetcher, ], - exports: [AaveV2ClaimableBalanceHelper, AaveV2ClaimableContractPositionHelper, AaveV2ContractFactory], }) export class AaveV2AppModule extends AbstractApp() {} diff --git a/src/apps/aave-v2/avalanche/aave-v2.claimable.contract-position-fetcher.ts b/src/apps/aave-v2/avalanche/aave-v2.claimable.contract-position-fetcher.ts index d5bd51264..474e845a7 100644 --- a/src/apps/aave-v2/avalanche/aave-v2.claimable.contract-position-fetcher.ts +++ b/src/apps/aave-v2/avalanche/aave-v2.claimable.contract-position-fetcher.ts @@ -1,9 +1,9 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2ClaimableTemplatePositionFetcher } from '../helpers/aave-v2.claimable.template.contract-position-fetcher'; +import { AaveV2ClaimablePositionFetcher } from '../common/aave-v2.claimable.contract-position-fetcher'; @PositionTemplate() -export class AvalancheAaveV2ClaimableContractPositionFetcher extends AaveV2ClaimableTemplatePositionFetcher { +export class AvalancheAaveV2ClaimableContractPositionFetcher extends AaveV2ClaimablePositionFetcher { groupLabel = 'Rewards'; isExcludedFromExplore = true; isExcludedFromTvl = true; diff --git a/src/apps/aave-v2/avalanche/aave-v2.stable-debt.token-fetcher.ts b/src/apps/aave-v2/avalanche/aave-v2.stable-debt.token-fetcher.ts index 5559234b6..6683ee9e9 100644 --- a/src/apps/aave-v2/avalanche/aave-v2.stable-debt.token-fetcher.ts +++ b/src/apps/aave-v2/avalanche/aave-v2.stable-debt.token-fetcher.ts @@ -1,16 +1,16 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class AvalancheAaveV2StableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class AvalancheAaveV2StableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x65285e9dfab318f57051ab2b139cccf232945451'; isDebt = true; diff --git a/src/apps/aave-v2/avalanche/aave-v2.supply.token-fetcher.ts b/src/apps/aave-v2/avalanche/aave-v2.supply.token-fetcher.ts index ca924e9a8..f5b8ba3af 100644 --- a/src/apps/aave-v2/avalanche/aave-v2.supply.token-fetcher.ts +++ b/src/apps/aave-v2/avalanche/aave-v2.supply.token-fetcher.ts @@ -1,16 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; - +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class AvalancheAaveV2SupplyTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class AvalancheAaveV2SupplyTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x65285e9dfab318f57051ab2b139cccf232945451'; isDebt = false; diff --git a/src/apps/aave-v2/avalanche/aave-v2.variable-debt.token-fetcher.ts b/src/apps/aave-v2/avalanche/aave-v2.variable-debt.token-fetcher.ts index ac801a7fc..4cd61341b 100644 --- a/src/apps/aave-v2/avalanche/aave-v2.variable-debt.token-fetcher.ts +++ b/src/apps/aave-v2/avalanche/aave-v2.variable-debt.token-fetcher.ts @@ -1,16 +1,16 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class AvalancheAaveV2VariableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class AvalancheAaveV2VariableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x65285e9dfab318f57051ab2b139cccf232945451'; isDebt = true; diff --git a/src/apps/aave-v2/helpers/aave-v2.claimable.template.contract-position-fetcher.ts b/src/apps/aave-v2/common/aave-v2.claimable.contract-position-fetcher.ts similarity index 97% rename from src/apps/aave-v2/helpers/aave-v2.claimable.template.contract-position-fetcher.ts rename to src/apps/aave-v2/common/aave-v2.claimable.contract-position-fetcher.ts index dd32c1180..3902b83cd 100644 --- a/src/apps/aave-v2/helpers/aave-v2.claimable.template.contract-position-fetcher.ts +++ b/src/apps/aave-v2/common/aave-v2.claimable.contract-position-fetcher.ts @@ -15,7 +15,7 @@ export type AaveV2ClaimableDataProps = { protocolDataProviderAddress: string; }; -export abstract class AaveV2ClaimableTemplatePositionFetcher extends ContractPositionTemplatePositionFetcher< +export abstract class AaveV2ClaimablePositionFetcher extends ContractPositionTemplatePositionFetcher< AaveStakedTokenIncentivesController, AaveV2ClaimableDataProps > { diff --git a/src/apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher.ts b/src/apps/aave-v2/common/aave-v2.lending.token-fetcher.ts similarity index 95% rename from src/apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher.ts rename to src/apps/aave-v2/common/aave-v2.lending.token-fetcher.ts index 4bf06f2d7..c57a51166 100644 --- a/src/apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher.ts +++ b/src/apps/aave-v2/common/aave-v2.lending.token-fetcher.ts @@ -13,7 +13,7 @@ import { import { AaveV2ContractFactory } from '../contracts'; import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; -export type AaveV2TemplateTokenDataProps = { +export type AaveV2TokenDataProps = { apy: number; enabledAsCollateral: boolean; liquidity: number; @@ -43,7 +43,7 @@ export type AaveV2LendingTokenDataProps = DefaultAppTokenDataProps & { liquidationThreshold: number; }; -export abstract class AaveV2LendingTemplateTokenFetcher extends AppTokenTemplatePositionFetcher< +export abstract class AaveV2LendingTokenFetcher extends AppTokenTemplatePositionFetcher< AaveV2AToken, AaveV2LendingTokenDataProps > { @@ -91,7 +91,7 @@ export abstract class AaveV2LendingTemplateTokenFetcher extends AppTokenTemplate async getReserveConfigDataProps({ appToken, multicall, - }: GetDataPropsParams): Promise { + }: GetDataPropsParams): Promise { const pool = multicall.wrap( this.contractFactory.aaveProtocolDataProvider({ network: this.network, diff --git a/src/apps/aave-v2/ethereum/aave-v2.claimable.contract-position-fetcher.ts b/src/apps/aave-v2/ethereum/aave-v2.claimable.contract-position-fetcher.ts index 1a570e72a..dec2d6311 100644 --- a/src/apps/aave-v2/ethereum/aave-v2.claimable.contract-position-fetcher.ts +++ b/src/apps/aave-v2/ethereum/aave-v2.claimable.contract-position-fetcher.ts @@ -1,9 +1,9 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2ClaimableTemplatePositionFetcher } from '../helpers/aave-v2.claimable.template.contract-position-fetcher'; +import { AaveV2ClaimablePositionFetcher } from '../common/aave-v2.claimable.contract-position-fetcher'; @PositionTemplate() -export class EthereumAaveV2ClaimableContractPositionFetcher extends AaveV2ClaimableTemplatePositionFetcher { +export class EthereumAaveV2ClaimableContractPositionFetcher extends AaveV2ClaimablePositionFetcher { groupLabel = 'Rewards'; isExcludedFromExplore = true; isExcludedFromTvl = true; diff --git a/src/apps/aave-v2/ethereum/aave-v2.stable-debt.token-fetcher.ts b/src/apps/aave-v2/ethereum/aave-v2.stable-debt.token-fetcher.ts index 24e87867a..4a5cd87fc 100644 --- a/src/apps/aave-v2/ethereum/aave-v2.stable-debt.token-fetcher.ts +++ b/src/apps/aave-v2/ethereum/aave-v2.stable-debt.token-fetcher.ts @@ -1,16 +1,16 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class EthereumAaveV2StableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class EthereumAaveV2StableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x057835ad21a177dbdd3090bb1cae03eacf78fc6d'; isDebt = true; diff --git a/src/apps/aave-v2/ethereum/aave-v2.supply.token-fetcher.ts b/src/apps/aave-v2/ethereum/aave-v2.supply.token-fetcher.ts index 6d5598ee1..79a4c510d 100644 --- a/src/apps/aave-v2/ethereum/aave-v2.supply.token-fetcher.ts +++ b/src/apps/aave-v2/ethereum/aave-v2.supply.token-fetcher.ts @@ -1,16 +1,16 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class EthereumAaveV2SupplyTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class EthereumAaveV2SupplyTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x057835ad21a177dbdd3090bb1cae03eacf78fc6d'; isDebt = false; diff --git a/src/apps/aave-v2/ethereum/aave-v2.variable-debt.token-fetcher.ts b/src/apps/aave-v2/ethereum/aave-v2.variable-debt.token-fetcher.ts index 92fb26b21..d5822d367 100644 --- a/src/apps/aave-v2/ethereum/aave-v2.variable-debt.token-fetcher.ts +++ b/src/apps/aave-v2/ethereum/aave-v2.variable-debt.token-fetcher.ts @@ -1,16 +1,16 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class EthereumAaveV2VariableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class EthereumAaveV2VariableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x057835ad21a177dbdd3090bb1cae03eacf78fc6d'; isDebt = true; diff --git a/src/apps/aave-v2/helpers/aave-v2.claimable.balance-helper.ts b/src/apps/aave-v2/helpers/aave-v2.claimable.balance-helper.ts deleted file mode 100644 index d37bdd9fd..000000000 --- a/src/apps/aave-v2/helpers/aave-v2.claimable.balance-helper.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { drillBalance } from '~app-toolkit/helpers/balance/token-balance.helper'; -import { ContractPositionBalance } from '~position/position-balance.interface'; -import { Network } from '~types/network.interface'; - -import { AaveV2ContractFactory } from '../contracts'; - -import { AaveV2ClaimableContractPositionDataProps } from './aave-v2.claimable.contract-position-helper'; - -type AaveV2ContractPositionHelperBuildClaimableParams = { - appId: string; - groupId: string; - network: Network; - address: string; -}; - -@Injectable() -export class AaveV2ClaimableBalanceHelper { - constructor( - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - @Inject(AaveV2ContractFactory) private readonly contractFactory: AaveV2ContractFactory, - ) {} - - async getClaimableBalances({ appId, groupId, network, address }: AaveV2ContractPositionHelperBuildClaimableParams) { - const contractFactory = this.contractFactory; - const multicall = this.appToolkit.getMulticall(network); - - // Retrieve reward token contract position - const [contractPosition] = await this.appToolkit.getAppContractPositions({ - network, - appId, - groupIds: [groupId], - }); - - // Build contracts for staked token incentives and protocol data provider - const { dataProps } = contractPosition; - const { incentivesControllerAddress, protocolDataProviderAddress } = dataProps; - const incentivesContract = contractFactory.aaveStakedTokenIncentivesController({ - network, - address: incentivesControllerAddress, - }); - const lendingContract = contractFactory.aaveProtocolDataProvider({ network, address: protocolDataProviderAddress }); - - // Resolve all supply, stable debt, and variable debt token addresses - const reserveTokens = await lendingContract.getAllReservesTokens(); - const reserveTokenAddresses = reserveTokens.map(v => v[1].toLowerCase()); - const tokenAddresses = await Promise.all( - reserveTokenAddresses.map(async reserveTokenAddress => { - const tokenAddresses = await multicall.wrap(lendingContract).getReserveTokensAddresses(reserveTokenAddress); - - return [ - tokenAddresses.aTokenAddress.toLowerCase(), - tokenAddresses.stableDebtTokenAddress.toLowerCase(), - tokenAddresses.variableDebtTokenAddress.toLowerCase(), - ]; - }), - ); - - // Retrieve emissions for each token address - const tokenAddressesFlat = tokenAddresses.flat(); - const tokenEmissions = await Promise.all( - tokenAddressesFlat.map(async reserveTokenAddress => { - const assetDetails = await multicall.wrap(incentivesContract).assets(reserveTokenAddress); - return Number(assetDetails.emissionPerSecond); - }), - ); - - // For assets earning non-zero emissions, retrieve claimable balances - const earningAddresses = tokenAddressesFlat.filter((_, i) => tokenEmissions[i] > 0); - const balanceRaw = await multicall.wrap(incentivesContract).getRewardsBalance(earningAddresses, address); - const tokenBalance = drillBalance(contractPosition.tokens[0], balanceRaw.toString()); - - const contractPositionBalance: ContractPositionBalance = { - ...contractPosition, - tokens: [tokenBalance], - balanceUSD: tokenBalance.balanceUSD, - }; - - return [contractPositionBalance]; - } -} diff --git a/src/apps/aave-v2/helpers/aave-v2.claimable.contract-position-helper.ts b/src/apps/aave-v2/helpers/aave-v2.claimable.contract-position-helper.ts deleted file mode 100644 index 7103de27d..000000000 --- a/src/apps/aave-v2/helpers/aave-v2.claimable.contract-position-helper.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { buildDollarDisplayItem } from '~app-toolkit/helpers/presentation/display-item.present'; -import { getTokenImg } from '~app-toolkit/helpers/presentation/image.present'; -import { ContractType } from '~position/contract.interface'; -import { ContractPosition } from '~position/position.interface'; -import { claimable } from '~position/position.utils'; -import { Network } from '~types/network.interface'; - -export type AaveV2ClaimableContractPositionDataProps = { - incentivesControllerAddress: string; - protocolDataProviderAddress: string; -}; - -type AaveV2VariableDebtTokenHelperParams = { - appId: string; - groupId: string; - network: Network; - incentivesControllerAddress: string; - protocolDataProviderAddress: string; - rewardTokenAddress: string; -}; - -@Injectable() -export class AaveV2ClaimableContractPositionHelper { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getTokens({ - appId, - groupId, - network, - incentivesControllerAddress, - protocolDataProviderAddress, - rewardTokenAddress, - }: AaveV2VariableDebtTokenHelperParams) { - const tokenSelector = this.appToolkit.getTokenDependencySelector({ tags: { network, context: appId } }); - const rewardToken = (await tokenSelector.getOne({ network, address: rewardTokenAddress }))!; - const tokens = [claimable(rewardToken)]; - - const position: ContractPosition = { - type: ContractType.POSITION, - address: incentivesControllerAddress, - network, - appId, - groupId, - tokens, - dataProps: { - incentivesControllerAddress, - protocolDataProviderAddress, - }, - displayProps: { - label: `Claimable ${rewardToken.symbol}`, - images: [getTokenImg(rewardToken.address, rewardToken.network)], - secondaryLabel: buildDollarDisplayItem(rewardToken.price), - }, - }; - - return [position]; - } -} diff --git a/src/apps/aave-v2/index.ts b/src/apps/aave-v2/index.ts index 7c4092d37..72cca0322 100644 --- a/src/apps/aave-v2/index.ts +++ b/src/apps/aave-v2/index.ts @@ -2,10 +2,6 @@ export { AAVE_V2_DEFINITION, AaveV2AppDefinition } from './aave-v2.definition'; export { AaveV2AppModule } from './aave-v2.module'; export { AaveV2ContractFactory } from './contracts'; -/* Helpers */ -export { AaveV2ClaimableBalanceHelper } from './helpers/aave-v2.claimable.balance-helper'; -export { AaveV2ClaimableContractPositionHelper } from './helpers/aave-v2.claimable.contract-position-helper'; - /* Contracts */ export type { AaveProtocolDataProvider } from './contracts'; export type { AaveStakedTokenIncentivesController } from './contracts'; diff --git a/src/apps/aave-v2/polygon/aave-v2.claimable.contract-position-fetcher.ts b/src/apps/aave-v2/polygon/aave-v2.claimable.contract-position-fetcher.ts index 2756821fc..edc36182f 100644 --- a/src/apps/aave-v2/polygon/aave-v2.claimable.contract-position-fetcher.ts +++ b/src/apps/aave-v2/polygon/aave-v2.claimable.contract-position-fetcher.ts @@ -1,9 +1,9 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2ClaimableTemplatePositionFetcher } from '../helpers/aave-v2.claimable.template.contract-position-fetcher'; +import { AaveV2ClaimablePositionFetcher } from '../common/aave-v2.claimable.contract-position-fetcher'; @PositionTemplate() -export class PolygonAaveV2ClaimableContractPositionFetcher extends AaveV2ClaimableTemplatePositionFetcher { +export class PolygonAaveV2ClaimableContractPositionFetcher extends AaveV2ClaimablePositionFetcher { groupLabel = 'Rewards'; isExcludedFromExplore = true; isExcludedFromTvl = true; diff --git a/src/apps/aave-v2/polygon/aave-v2.stable-debt.token-fetcher.ts b/src/apps/aave-v2/polygon/aave-v2.stable-debt.token-fetcher.ts index e72f92592..2b71a798d 100644 --- a/src/apps/aave-v2/polygon/aave-v2.stable-debt.token-fetcher.ts +++ b/src/apps/aave-v2/polygon/aave-v2.stable-debt.token-fetcher.ts @@ -1,16 +1,16 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class PolygonAaveV2StableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class PolygonAaveV2StableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x7551b5d2763519d4e37e8b81929d336de671d46d'; isDebt = true; diff --git a/src/apps/aave-v2/polygon/aave-v2.supply.token-fetcher.ts b/src/apps/aave-v2/polygon/aave-v2.supply.token-fetcher.ts index 2bf7ba729..c9e577173 100644 --- a/src/apps/aave-v2/polygon/aave-v2.supply.token-fetcher.ts +++ b/src/apps/aave-v2/polygon/aave-v2.supply.token-fetcher.ts @@ -5,12 +5,12 @@ import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; @PositionTemplate() -export class PolygonAaveV2SupplyTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class PolygonAaveV2SupplyTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x7551b5d2763519d4e37e8b81929d336de671d46d'; isDebt = false; diff --git a/src/apps/aave-v2/polygon/aave-v2.variable-debt.token-fetcher.ts b/src/apps/aave-v2/polygon/aave-v2.variable-debt.token-fetcher.ts index b25847bba..179e1b238 100644 --- a/src/apps/aave-v2/polygon/aave-v2.variable-debt.token-fetcher.ts +++ b/src/apps/aave-v2/polygon/aave-v2.variable-debt.token-fetcher.ts @@ -1,16 +1,16 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; -import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; import { AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, -} from '../helpers/aave-v2.lending.template.token-fetcher'; +} from '../common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '../contracts/ethers/AaveV2AToken'; @PositionTemplate() -export class PolygonAaveV2VariableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class PolygonAaveV2VariableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x7551b5d2763519d4e37e8b81929d336de671d46d'; isDebt = true; diff --git a/src/apps/agave/gnosis/agave.claimable.contract-position-fetcher.ts b/src/apps/agave/gnosis/agave.claimable.contract-position-fetcher.ts index a17552bf4..e989f1529 100644 --- a/src/apps/agave/gnosis/agave.claimable.contract-position-fetcher.ts +++ b/src/apps/agave/gnosis/agave.claimable.contract-position-fetcher.ts @@ -1,8 +1,8 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2ClaimableTemplatePositionFetcher } from '~apps/aave-v2/helpers/aave-v2.claimable.template.contract-position-fetcher'; +import { AaveV2ClaimablePositionFetcher } from '~apps/aave-v2/common/aave-v2.claimable.contract-position-fetcher'; @PositionTemplate() -export class GnosisAgaveClaimableContractPositionFetcher extends AaveV2ClaimableTemplatePositionFetcher { +export class GnosisAgaveClaimableContractPositionFetcher extends AaveV2ClaimablePositionFetcher { groupLabel = 'Rewards'; isExcludedFromExplore = true; isExcludedFromTvl = true; diff --git a/src/apps/agave/gnosis/agave.deposit.token-fetcher.ts b/src/apps/agave/gnosis/agave.deposit.token-fetcher.ts index 68e146f6f..9f2700b11 100644 --- a/src/apps/agave/gnosis/agave.deposit.token-fetcher.ts +++ b/src/apps/agave/gnosis/agave.deposit.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2AToken } from '~apps/aave-v2/contracts/ethers/AaveV2AToken'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '~apps/aave-v2/contracts/ethers/AaveV2AToken'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class GnosisAgaveDepositTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class GnosisAgaveDepositTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x24dcbd376db23e4771375092344f5cbea3541fc0'; isDebt = false; diff --git a/src/apps/agave/gnosis/agave.stable-borrow.token-fetcher.ts b/src/apps/agave/gnosis/agave.stable-borrow.token-fetcher.ts index bf34f5db5..f35e6f9ef 100644 --- a/src/apps/agave/gnosis/agave.stable-borrow.token-fetcher.ts +++ b/src/apps/agave/gnosis/agave.stable-borrow.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class GnosisAgaveStableBorrowTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class GnosisAgaveStableBorrowTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x24dcbd376db23e4771375092344f5cbea3541fc0'; isDebt = true; diff --git a/src/apps/agave/gnosis/agave.variable-borrow.token-fetcher.ts b/src/apps/agave/gnosis/agave.variable-borrow.token-fetcher.ts index 44243bfbf..3fe742462 100644 --- a/src/apps/agave/gnosis/agave.variable-borrow.token-fetcher.ts +++ b/src/apps/agave/gnosis/agave.variable-borrow.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class GnosisAgaveVariableBorrowTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class GnosisAgaveVariableBorrowTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x24dcbd376db23e4771375092344f5cbea3541fc0'; isDebt = true; diff --git a/src/apps/b-protocol/adapters/compound.b-protocol-adapter.ts b/src/apps/b-protocol/adapters/compound.b-protocol-adapter.ts deleted file mode 100644 index b04104f11..000000000 --- a/src/apps/b-protocol/adapters/compound.b-protocol-adapter.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { ZERO_ADDRESS } from '~app-toolkit/constants/address'; -import { COMPOUND_DEFINITION } from '~apps/compound/compound.definition'; -import { CompoundContractFactory } from '~apps/compound/contracts'; -import { CompoundBorrowBalanceHelper } from '~apps/compound/helper/compound.borrow.balance-helper'; -import { CompoundLendingMetaHelper } from '~apps/compound/helper/compound.lending.meta-helper'; -import { CompoundSupplyBalanceHelper } from '~apps/compound/helper/compound.supply.balance-helper'; -import { ProductItem } from '~balance/balance-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { BProtocolContractFactory } from '../contracts'; - -const network = Network.ETHEREUM_MAINNET; - -export class CompoundBProtocolAdapter { - constructor( - @Inject(CompoundBorrowBalanceHelper) private readonly compoundBorrowBalanceHelper: CompoundBorrowBalanceHelper, - @Inject(CompoundSupplyBalanceHelper) private readonly compoundSupplyBalanceHelper: CompoundSupplyBalanceHelper, - @Inject(CompoundContractFactory) private readonly compoundContractFactory: CompoundContractFactory, - @Inject(CompoundLendingMetaHelper) private readonly compoundLendingMetaHelper: CompoundLendingMetaHelper, - @Inject(BProtocolContractFactory) private readonly bProtocolContractFactory: BProtocolContractFactory, - ) {} - - async getBalances(address: string): Promise { - const registry = this.bProtocolContractFactory.bProtocolCompoundRegistry({ - address: '0xbf698df5591caf546a7e087f5806e216afed666a', - network, - }); - - const avatarAddress = await registry.avatarOf(address); - if (avatarAddress === ZERO_ADDRESS) return null; - - const [borrowBalances, supplyBalances] = await Promise.all([ - this.compoundBorrowBalanceHelper.getBalances({ - address: avatarAddress, - appId: COMPOUND_DEFINITION.id, - groupId: COMPOUND_DEFINITION.groups.borrow.id, - network, - getTokenContract: ({ address, network }) => this.compoundContractFactory.compoundCToken({ address, network }), - getBorrowBalanceRaw: ({ contract, address, multicall }) => - multicall.wrap(contract).borrowBalanceCurrent(address), - }), - this.compoundSupplyBalanceHelper.getBalances({ - address: avatarAddress, - appId: COMPOUND_DEFINITION.id, - groupId: COMPOUND_DEFINITION.groups.supply.id, - network, - getTokenContract: ({ address, network }) => this.compoundContractFactory.compoundCToken({ address, network }), - getBalanceRaw: ({ contract, address, multicall }) => multicall.wrap(contract).balanceOf(address), - }), - ]); - - const meta = this.compoundLendingMetaHelper.getMeta({ balances: [...supplyBalances, ...borrowBalances] }); - - return { - label: 'Compound', - assets: [...supplyBalances, ...borrowBalances], - meta, - }; - } -} diff --git a/src/apps/b-protocol/adapters/liquity.b-protocol-adapter.ts b/src/apps/b-protocol/adapters/liquity.b-protocol-adapter.ts deleted file mode 100644 index f515e0dfa..000000000 --- a/src/apps/b-protocol/adapters/liquity.b-protocol-adapter.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { Inject } from '@nestjs/common'; -import _ from 'lodash'; - -import { drillBalance } from '~app-toolkit'; -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { buildDollarDisplayItem } from '~app-toolkit/helpers/presentation/display-item.present'; -import { getTokenImg } from '~app-toolkit/helpers/presentation/image.present'; -import { LIQUITY_DEFINITION } from '~apps/liquity'; -import { ProductItem } from '~balance/balance-fetcher.interface'; -import { ContractType } from '~position/contract.interface'; -import { ContractPositionBalance } from '~position/position-balance.interface'; -import { Network } from '~types/network.interface'; - -import { BProtocolContractFactory } from '../contracts'; - -const appId = LIQUITY_DEFINITION.id; -const groupId = LIQUITY_DEFINITION.groups.trove.id; -const network = Network.ETHEREUM_MAINNET; - -export class LiquityBProtocolAdapter { - private readonly bammPools = [ - '0x00ff66ab8699aafa050ee5ef5041d1503aa0849a', - '0x0d3abaa7e088c2c82f54b2f47613da438ea8c598', - '0x54bc9113f1f55cdbdf221daf798dc73614f6d972', - ]; - - constructor( - @Inject(BProtocolContractFactory) private readonly bProtocolContractFactory: BProtocolContractFactory, - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - ) {} - - async getBalances(address: string): Promise { - const multicall = this.appToolkit.getMulticall(network); - const baseTokens = await this.appToolkit.getBaseTokenPrices(network); - - const bammLensAddress = '0xfae2e2d3f11bab10ee0ddd0332f6dfe957414ccb'; - const contract = this.bProtocolContractFactory.bProtocolBammLens({ address: bammLensAddress, network }); - const wrappedContract = multicall.wrap(contract); - - const liquityBalancesRaw = await Promise.all( - this.bammPools.map(async pool => { - const userDeposits = await wrappedContract.getUserDeposit(address, pool); - const lusdToken = baseTokens.find(p => p.symbol === 'LUSD'); - const ethToken = baseTokens.find(p => p.symbol === 'ETH'); - if (!lusdToken || !ethToken) return null; - - return [ - { token: lusdToken, balanceRaw: userDeposits.lusd }, - { token: ethToken, balanceRaw: userDeposits.eth }, - ].map(({ token, balanceRaw }) => { - const tokenBalance = drillBalance(token, balanceRaw.toString()); - - const contractPositionBalance: ContractPositionBalance = { - type: ContractType.POSITION, - address: bammLensAddress, - appId, - groupId, - network, - tokens: [tokenBalance], - balanceUSD: tokenBalance.balanceUSD, - dataProps: {}, - displayProps: { - label: `Deposited ${token.symbol} in Liquity`, - secondaryLabel: buildDollarDisplayItem(token.price), - images: [getTokenImg(token.address, network)], - }, - }; - - return contractPositionBalance; - }); - }), - ); - - const liquityBalances = _.compact(liquityBalancesRaw); - - return { - label: 'Liquity', - assets: liquityBalances.flat(), - meta: [], - }; - } -} diff --git a/src/apps/b-protocol/adapters/maker.b-protocol.adapter.ts b/src/apps/b-protocol/adapters/maker.b-protocol.adapter.ts deleted file mode 100644 index f99193262..000000000 --- a/src/apps/b-protocol/adapters/maker.b-protocol.adapter.ts +++ /dev/null @@ -1,145 +0,0 @@ -import { Inject } from '@nestjs/common'; -import _ from 'lodash'; -import { sumBy } from 'lodash'; - -import { drillBalance } from '~app-toolkit'; -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { getImagesFromToken } from '~app-toolkit/helpers/presentation/image.present'; -import { MAKER_DEFINITION } from '~apps/maker'; -import { ProductItem } from '~balance/balance-fetcher.interface'; -import { ContractType } from '~position/contract.interface'; -import { ContractPositionBalance } from '~position/position-balance.interface'; -import { Network } from '~types/network.interface'; - -import { BProtocolContractFactory } from '../contracts'; - -const appId = MAKER_DEFINITION.id; -const groupId = MAKER_DEFINITION.groups.vault.id; -const network = Network.ETHEREUM_MAINNET; - -export class MakerBProtocolAdapter { - private readonly BCDP_MANGER = '0x3f30c2381cd8b917dd96eb2f1a4f96d91324bbed'; - private readonly CDP_MANAGER = '0x5ef30b9986345249bc32d8928b7ee64de9435e39'; - private readonly GET_CDPS = '0x36a724bd100c39f0ea4d3a20f7097ee01a8ff573'; - private readonly MCD_VAT = '0x35d1b3f3d7966a1dfe207aa4514c12a259a0492b'; - private readonly MCD_SPOT = '0x65c79fcb50ca1594b025960e539ed7a9a6d434a3'; - private readonly PROXY_REGISTRY = '0x4678f0a6958e4d2bc4f1baf7bc52e8f3564f3fe4'; - private readonly JAR = '0x3c36ccf03dab88c1b1ac1eb9c3fb5db0b6763cff'; - private readonly ILKs = [ - { - name: 'ETH-A', - code: '0x4554482d41000000000000000000000000000000000000000000000000000000', - }, - { - name: 'ETH-B', - code: '0x4554482d42000000000000000000000000000000000000000000000000000000', - }, - { - name: 'ETH-C', - code: '0x4554482d43000000000000000000000000000000000000000000000000000000', - }, - { - name: 'WBTC-A', - code: '0x574254432d410000000000000000000000000000000000000000000000000000', - }, - ]; - - constructor( - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - @Inject(BProtocolContractFactory) private readonly bProtocolContractFactory: BProtocolContractFactory, - ) {} - - async getBalances(address: string): Promise { - const baseTokens = await this.appToolkit.getBaseTokenPrices(network); - const contract = this.bProtocolContractFactory.bProtocolGetInfo({ - address: '0x468960199c8045dedcf6aeb33e28dc57346ad3ff', - network, - }); - - const makerBalancesRaw = await Promise.all( - this.ILKs.map(async ilk => { - const userInfo = await contract.callStatic.getInfo( - address, - ilk.code, - this.BCDP_MANGER, - this.CDP_MANAGER, - this.GET_CDPS, - this.MCD_VAT, - this.MCD_SPOT, - this.PROXY_REGISTRY, - this.JAR, - ); - - // Data Props - const vaultID = Number(userInfo.bCdpInfo.cdp); - const tokenSymbol = ilk.name.split('-')[0]; - const collateralToken = baseTokens.find(p => p.symbol === tokenSymbol); - const debtToken = baseTokens.find(p => p.symbol === 'DAI'); - if (!collateralToken || !debtToken) return null; - - const collateral = drillBalance(collateralToken, userInfo.bCdpInfo.ethDeposit.toString()); - const debt = drillBalance(debtToken, userInfo.bCdpInfo.daiDebt.toString(), { isDebt: true }); - const tokens = [collateral, debt].filter(v => Math.abs(v.balanceUSD) > 0); - const balanceUSD = sumBy(tokens, v => v.balanceUSD); - const cRatio = debt.balanceUSD === 0 ? 0 : (collateral.balanceUSD / Math.abs(debt.balanceUSD)) * 100; - - // Display Props - const label = `Maker Vault #${vaultID}`; - const images = tokens.map(v => getImagesFromToken(v)).flat(); - - const position: ContractPositionBalance = { - type: ContractType.POSITION, - address: this.BCDP_MANGER, - appId, - groupId, - network, - tokens, - balanceUSD, - - dataProps: { - cRatio, - }, - - displayProps: { - label, - images, - }, - }; - - return position; - }), - ); - - const makerBalances = _.compact(makerBalancesRaw); - - const [collateral, debt] = _.partition( - makerBalances.flatMap(v => v.tokens), - v => v.balanceUSD >= 0, - ); - const collateralUSD = sumBy(collateral, a => a.balanceUSD); - const debtUSD = sumBy(debt, a => a.balanceUSD); - const cRatio = debtUSD === 0 ? 0 : (collateralUSD / Math.abs(debtUSD)) * 100; - - return { - label: 'Maker', - assets: makerBalances.flat(), - meta: [ - { - label: 'Collateral', - value: collateralUSD, - type: 'dollar', - }, - { - label: 'Debt', - value: debtUSD, - type: 'dollar', - }, - { - label: 'C-Ratio', - value: cRatio, - type: 'pct', - }, - ], - }; - } -} diff --git a/src/apps/balancer-v2/balancer-v2.module.ts b/src/apps/balancer-v2/balancer-v2.module.ts index f42fa793c..d730091d7 100644 --- a/src/apps/balancer-v2/balancer-v2.module.ts +++ b/src/apps/balancer-v2/balancer-v2.module.ts @@ -42,6 +42,5 @@ import { PolygonBalancerV2StaticYieldTokenFetcher } from './polygon/balancer-v2. BalancerV2ClaimableCacheManager, BalancerV2SpotPriceHelper, ], - exports: [BalancerV2SpotPriceHelper, BalancerV2ContractFactory], }) export class BalancerV2AppModule extends AbstractApp() {} diff --git a/src/apps/beefy/beefy.module.ts b/src/apps/beefy/beefy.module.ts index 672c4f53c..81578f78d 100644 --- a/src/apps/beefy/beefy.module.ts +++ b/src/apps/beefy/beefy.module.ts @@ -45,6 +45,5 @@ import { PolygonBeefyVaultTokenFetcher } from './polygon/beefy.vault.token-fetch OptimismBeefyVaultTokenFetcher, OptimismBeefyBoostVaultContractPositionFetcher, ], - exports: [BeefyAppDefinition, BeefyContractFactory], }) export class BeefyAppModule extends AbstractApp() {} diff --git a/src/apps/compound/compound.module.ts b/src/apps/compound/compound.module.ts index 9c20a651a..0ddea2068 100644 --- a/src/apps/compound/compound.module.ts +++ b/src/apps/compound/compound.module.ts @@ -8,13 +8,6 @@ import { EthereumCompoundBorrowContractPositionFetcher } from './ethereum/compou import { EthereumCompoundClaimableContractPositionFetcher } from './ethereum/compound.claimable.contract-position-fetcher'; import { EthereumCompoundPositionPresenter } from './ethereum/compound.position-presenter'; import { EthereumCompoundSupplyTokenFetcher } from './ethereum/compound.supply.token-fetcher'; -import { CompoundBorrowBalanceHelper } from './helper/compound.borrow.balance-helper'; -import { CompoundBorrowContractPositionHelper } from './helper/compound.borrow.contract-position-helper'; -import { CompoundClaimableBalanceHelper } from './helper/compound.claimable.balance-helper'; -import { CompoundClaimableContractPositionHelper } from './helper/compound.claimable.contract-position-helper'; -import { CompoundLendingMetaHelper } from './helper/compound.lending.meta-helper'; -import { CompoundSupplyBalanceHelper } from './helper/compound.supply.balance-helper'; -import { CompoundSupplyTokenHelper } from './helper/compound.supply.token-helper'; @Module({ providers: [ @@ -24,25 +17,6 @@ import { CompoundSupplyTokenHelper } from './helper/compound.supply.token-helper EthereumCompoundPositionPresenter, EthereumCompoundClaimableContractPositionFetcher, EthereumCompoundSupplyTokenFetcher, - // Helpers - CompoundBorrowBalanceHelper, - CompoundBorrowContractPositionHelper, - CompoundClaimableBalanceHelper, - CompoundClaimableContractPositionHelper, - CompoundContractFactory, - CompoundLendingMetaHelper, - CompoundSupplyBalanceHelper, - CompoundSupplyTokenHelper, - ], - exports: [ - CompoundBorrowBalanceHelper, - CompoundBorrowContractPositionHelper, - CompoundClaimableBalanceHelper, - CompoundClaimableContractPositionHelper, - CompoundContractFactory, - CompoundLendingMetaHelper, - CompoundSupplyBalanceHelper, - CompoundSupplyTokenHelper, ], }) export class CompoundAppModule extends AbstractApp() {} diff --git a/src/apps/compound/helper/compound.borrow.balance-helper.ts b/src/apps/compound/helper/compound.borrow.balance-helper.ts deleted file mode 100644 index f6bbfc9bb..000000000 --- a/src/apps/compound/helper/compound.borrow.balance-helper.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; - -import { drillBalance } from '~app-toolkit'; -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { borrowed } from '~position/position.utils'; -import { Network } from '~types/network.interface'; - -import { CompoundCToken } from '../contracts'; - -import { CompoundSupplyTokenDataProps } from './compound.supply.token-helper'; - -type CompoundBorrowBalanceHelperParams = { - address: string; - network: Network; - appId: string; - groupId: string; - getTokenContract: (opts: { address: string; network: Network }) => T; - getBorrowBalanceRaw: (opts: { contract: T; multicall: IMulticallWrapper; address: string }) => Promise; -}; - -@Injectable() -export class CompoundBorrowBalanceHelper { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getBalances({ - address, - network, - appId, - groupId, - getTokenContract, - getBorrowBalanceRaw, - }: CompoundBorrowBalanceHelperParams) { - const multicall = this.appToolkit.getMulticall(network); - - const borrowPositions = await this.appToolkit.getAppContractPositions({ - appId, - groupIds: [groupId], - network, - }); - - const borrowPositionBalances = await Promise.all( - borrowPositions.map(async borrowPosition => { - const borrowContract = getTokenContract({ address: borrowPosition.address, network }); - const balanceRaw = await getBorrowBalanceRaw({ contract: borrowContract, multicall, address }); - const tokens = [drillBalance(borrowed(borrowPosition.tokens[0]), balanceRaw.toString(), { isDebt: true })]; - return { ...borrowPosition, tokens, balanceUSD: tokens[0].balanceUSD }; - }), - ); - - return borrowPositionBalances; - } -} diff --git a/src/apps/compound/helper/compound.borrow.contract-position-helper.ts b/src/apps/compound/helper/compound.borrow.contract-position-helper.ts deleted file mode 100644 index 97fc91db2..000000000 --- a/src/apps/compound/helper/compound.borrow.contract-position-helper.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; -import { isNumber } from 'lodash'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { - buildDollarDisplayItem, - buildPercentageDisplayItem, -} from '~app-toolkit/helpers/presentation/display-item.present'; -import { getLabelFromToken } from '~app-toolkit/helpers/presentation/image.present'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { ContractType } from '~position/contract.interface'; -import { ContractPosition } from '~position/position.interface'; -import { borrowed } from '~position/position.utils'; -import { Network } from '~types/network.interface'; - -import { CompoundContractFactory, CompoundCToken } from '../contracts'; - -import { CompoundSupplyTokenDataProps } from './compound.supply.token-helper'; - -export type CompoundBorrowContractPositionDataProps = CompoundSupplyTokenDataProps & { - supply: number; - borrow: number; -}; - -type CompoundBorrowContractPositionHelperParams = { - network: Network; - appId: string; - groupId: string; - supplyGroupId: string; - resolveCashRaw?: (opts: { - contract: CompoundCToken; - address: string; - network: Network; - multicall: IMulticallWrapper; - }) => Promise; -}; - -@Injectable() -export class CompoundBorrowContractPositionHelper { - constructor( - @Inject(CompoundContractFactory) private readonly contractFactory: CompoundContractFactory, - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - ) {} - - async getPositions({ - network, - appId, - groupId, - supplyGroupId, - resolveCashRaw = ({ contract, multicall }) => multicall.wrap(contract).getCash(), - }: CompoundBorrowContractPositionHelperParams) { - const appTokens = await this.appToolkit.getAppTokenPositions({ - appId, - groupIds: [supplyGroupId], - network, - }); - - const multicall = this.appToolkit.getMulticall(network); - const promisedPositions = appTokens.map(async appToken => { - const contract = this.contractFactory.compoundCToken({ network, address: appToken.address }); - - // Compound has a `getCash` method which returns the total liquidity - // of a given borrowed contract position. This is typically what defilama - // would use to display a TVL - const cashRaw = await resolveCashRaw({ multicall, contract, address: appToken.address, network }).catch(() => 0); - // The "cash" needs to be converted back into a proper number format. - // We use the underlying token as the basis for the conversion. - const cashSupply = Number(cashRaw) / 10 ** appToken.tokens[0].decimals; - - const tokens = [borrowed(appToken.tokens[0])]; - // The underlying token liquidity actually represents the TOTAL SUPPLY of a borrowed - // contract position, not the liquidity. - const underlyingLiquidity = appToken.dataProps.liquidity; - const underlyingPrice = appToken.tokens[0].price; - // Liquidity is the total supply of "cash" multiplied by the price of an underlying token - const borrowedPositionliquidity = cashSupply * underlyingPrice; - - const borrowLiquidity = - borrowedPositionliquidity > underlyingLiquidity ? 0 : underlyingLiquidity - borrowedPositionliquidity; - - const dataProps = { - ...appToken.dataProps, - liquidity: -borrowLiquidity, - supply: underlyingLiquidity, - // The amount borrowed can be derived simply by substracting the liquidity from the total supply - // of tokens - borrow: borrowLiquidity, - isActive: Boolean(borrowLiquidity > 0), - }; - const borrowApy = appToken.dataProps.borrowApy; - - // Display Props - const label = getLabelFromToken(appToken.tokens[0]); - const secondaryLabel = buildDollarDisplayItem(underlyingPrice); - const tertiaryLabel = isNumber(borrowApy) ? `${(borrowApy * 100).toFixed(3)}% APY` : ''; - const images = appToken.displayProps.images; - const statsItems = isNumber(borrowApy) - ? [ - { label: 'APY', value: buildPercentageDisplayItem(borrowApy * 100) }, - { label: 'Liquidity', value: buildDollarDisplayItem(borrowLiquidity) }, - ] - : []; - - const contractPosition: ContractPosition = { - type: ContractType.POSITION, - address: appToken.address, - network, - appId, - groupId, - tokens, - dataProps, - displayProps: { - label, - secondaryLabel, - tertiaryLabel, - images, - statsItems, - }, - }; - - return contractPosition; - }); - - const positions = await Promise.all(promisedPositions); - - return positions; - } -} diff --git a/src/apps/compound/helper/compound.claimable.balance-helper.ts b/src/apps/compound/helper/compound.claimable.balance-helper.ts deleted file mode 100644 index 3421f8609..000000000 --- a/src/apps/compound/helper/compound.claimable.balance-helper.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; - -import { drillBalance } from '~app-toolkit'; -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { Network } from '~types/network.interface'; - -import { CompoundContractFactory } from '../contracts'; - -import { CompoundClaimablePositionDataProps } from './compound.claimable.contract-position-helper'; - -type CompoundBalanceHelperParams = { - address: string; - network: Network; - appId: string; - groupId: string; -}; - -@Injectable() -export class CompoundClaimableBalanceHelper { - constructor( - @Inject(CompoundContractFactory) private readonly compoundContractFactory: CompoundContractFactory, - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - ) {} - - async getBalances({ address, network, appId, groupId }: CompoundBalanceHelperParams) { - return this.appToolkit.helpers.contractPositionBalanceHelper.getContractPositionBalances( - { - network, - appId, - groupId, - address, - resolveBalances: async ({ address, network, contractPosition }) => { - const [rewardToken] = contractPosition.tokens; - const { - address: comptrollerAddress, - dataProps: { lensAddress }, - } = contractPosition; - - const lensContract = this.compoundContractFactory.compoundLens({ address: lensAddress, network }); - const rewardMetadata = await lensContract.callStatic.getCompBalanceMetadataExt( - rewardToken.address, - comptrollerAddress, - address, - ); - - const rewardBalanceRaw = rewardMetadata[3]; - return [drillBalance(rewardToken, rewardBalanceRaw.toString())]; - }, - }, - ); - } -} diff --git a/src/apps/compound/helper/compound.claimable.contract-position-helper.ts b/src/apps/compound/helper/compound.claimable.contract-position-helper.ts deleted file mode 100644 index 887c45420..000000000 --- a/src/apps/compound/helper/compound.claimable.contract-position-helper.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { buildDollarDisplayItem } from '~app-toolkit/helpers/presentation/display-item.present'; -import { getTokenImg } from '~app-toolkit/helpers/presentation/image.present'; -import { ContractType } from '~position/contract.interface'; -import { ContractPosition, MetaType } from '~position/position.interface'; -import { Network } from '~types/network.interface'; - -export type CompoundClaimablePositionDataProps = { - lensAddress: string; -}; - -type CompoundBalanceHelperParams = { - network: Network; - appId: string; - groupId: string; - lensAddress: string; - rewardTokenAddress: string; - comptrollerAddress: string; -}; - -@Injectable() -export class CompoundClaimableContractPositionHelper { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getPositions({ - network, - appId, - groupId, - lensAddress, - rewardTokenAddress, - comptrollerAddress, - }: CompoundBalanceHelperParams) { - const tokenSelector = this.appToolkit.getTokenDependencySelector({ tags: { network, context: appId } }); - - // Calculate claimable COMP rewards - const rewardToken = (await tokenSelector.getOne({ network, address: rewardTokenAddress }))!; - const rewardTokenWithMetaType = { metaType: MetaType.CLAIMABLE, ...rewardToken }; - - // Display Props - const label = `Claimable ${rewardToken.symbol}`; - const secondaryLabel = buildDollarDisplayItem(rewardToken.price); - const images = [getTokenImg(rewardToken.address, network)]; - const statsItems = []; - const displayProps = { label, secondaryLabel, images, statsItems }; - - const contractPosition: ContractPosition = { - type: ContractType.POSITION, - address: comptrollerAddress, - appId, - groupId, - network, - dataProps: { lensAddress }, - displayProps, - tokens: [rewardTokenWithMetaType], - }; - - return [contractPosition]; - } -} diff --git a/src/apps/compound/helper/compound.lending.meta-helper.ts b/src/apps/compound/helper/compound.lending.meta-helper.ts deleted file mode 100644 index b0d994574..000000000 --- a/src/apps/compound/helper/compound.lending.meta-helper.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { sumBy } from 'lodash'; - -import { MetadataItemWithLabel } from '~balance/balance-fetcher.interface'; -import { ContractPositionBalance, TokenBalance } from '~position/position-balance.interface'; - -type CompoundLendingMetaHelperParams = { - balances: (TokenBalance | ContractPositionBalance)[]; -}; - -@Injectable() -export class CompoundLendingMetaHelper { - getMeta({ balances }: CompoundLendingMetaHelperParams) { - const collaterals = balances.filter(balance => balance.balanceUSD > 0); - const debt = balances.filter(balance => balance.balanceUSD < 0); - const totalCollateralUSD = sumBy(collaterals, a => a.balanceUSD); - const totalDebtUSD = sumBy(debt, a => a.balanceUSD); - const utilRatio = (Math.abs(totalDebtUSD) / totalCollateralUSD) * 100; - - const meta: MetadataItemWithLabel[] = [ - { - label: 'Collateral', - value: totalCollateralUSD, - type: 'dollar', - }, - { - label: 'Debt', - value: totalDebtUSD, - type: 'dollar', - }, - { - label: 'Utilization Rate', - value: utilRatio, - type: 'pct', - }, - ]; - - return meta; - } -} diff --git a/src/apps/compound/helper/compound.supply.balance-helper.ts b/src/apps/compound/helper/compound.supply.balance-helper.ts deleted file mode 100644 index 271dae890..000000000 --- a/src/apps/compound/helper/compound.supply.balance-helper.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; - -import { drillBalance } from '~app-toolkit'; -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { Network } from '~types/network.interface'; - -import { CompoundCToken } from '../contracts'; - -import { CompoundSupplyTokenDataProps } from './compound.supply.token-helper'; - -type CompoundSupplyBalanceHelperParams = { - address: string; - network: Network; - appId: string; - groupId: string; - getTokenContract: (opts: { address: string; network: Network }) => T; - getBalanceRaw: (opts: { contract: T; multicall: IMulticallWrapper; address: string }) => Promise; -}; - -@Injectable() -export class CompoundSupplyBalanceHelper { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getBalances({ - address, - network, - appId, - groupId, - getTokenContract, - getBalanceRaw, - }: CompoundSupplyBalanceHelperParams) { - const multicall = this.appToolkit.getMulticall(network); - - const supplyTokens = await this.appToolkit.getAppTokenPositions({ - appId, - groupIds: [groupId], - network, - }); - - const supplyTokenBalances = await Promise.all( - supplyTokens.map(async supplyToken => { - const supplyTokenContract = getTokenContract({ address: supplyToken.address, network }); - const balanceRaw = await getBalanceRaw({ contract: supplyTokenContract, multicall, address }); - return drillBalance(supplyToken, balanceRaw.toString()); - }), - ); - - return supplyTokenBalances; - } -} diff --git a/src/apps/compound/helper/compound.supply.token-helper.ts b/src/apps/compound/helper/compound.supply.token-helper.ts deleted file mode 100644 index d2c4b9424..000000000 --- a/src/apps/compound/helper/compound.supply.token-helper.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; -import _, { compact } from 'lodash'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { ETH_ADDR_ALIAS, ZERO_ADDRESS } from '~app-toolkit/constants/address'; -import { BLOCKS_PER_DAY } from '~app-toolkit/constants/blocks'; -import { - buildDollarDisplayItem, - buildPercentageDisplayItem, -} from '~app-toolkit/helpers/presentation/display-item.present'; -import { getTokenImg } from '~app-toolkit/helpers/presentation/image.present'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { ContractType } from '~position/contract.interface'; -import { BalanceDisplayMode } from '~position/display.interface'; -import { AppTokenPosition, ExchangeableAppTokenDataProps, Token } from '~position/position.interface'; -import { Network } from '~types/network.interface'; - -import { CompoundComptroller, CompoundContractFactory, CompoundCToken } from '../contracts'; - -export type CompoundSupplyTokenDataProps = ExchangeableAppTokenDataProps & { - supplyApy: number; - borrowApy: number; - liquidity: number; - marketName?: string; - comptrollerAddress: string; -}; - -type CompoundSupplyTokenHelperParams = { - network: Network; - appId: string; - groupId: string; - comptrollerAddress: string; - marketName?: string; - getComptrollerContract: (opts: { address: string; network: Network }) => T; - getTokenContract: (opts: { address: string; network: Network }) => V; - getAllMarkets: (opts: { contract: T; multicall: IMulticallWrapper }) => string[] | Promise; - getExchangeRate: (opts: { contract: V; multicall: IMulticallWrapper }) => Promise; - getSupplyRate: (opts: { contract: V; multicall: IMulticallWrapper }) => Promise; - getBorrowRate: (opts: { contract: V; multicall: IMulticallWrapper }) => Promise; - getSupplyRateLabel?: () => string; - getUnderlyingAddress: (opts: { contract: V; multicall: IMulticallWrapper }) => Promise; - getExchangeRateMantissa: (opts: { tokenDecimals: number; underlyingTokenDecimals: number }) => number; - getDisplayLabel?: (opts: { contract: V; multicall: IMulticallWrapper; underlyingToken: Token }) => Promise; - getDenormalizedRate?: (opts: { rate: BigNumberish; blocksPerDay: number; decimals: number }) => number; - exchangeable?: boolean; -}; - -@Injectable() -export class CompoundSupplyTokenHelper { - constructor( - @Inject(CompoundContractFactory) private readonly contractFactory: CompoundContractFactory, - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - ) {} - - async getTokens({ - comptrollerAddress, - marketName, - network, - appId, - groupId, - exchangeable = false, - getComptrollerContract, - getTokenContract, - getAllMarkets, - getExchangeRate, - getSupplyRate, - getBorrowRate, - getSupplyRateLabel = () => 'APY', - getUnderlyingAddress, - getExchangeRateMantissa, - getDisplayLabel, - getDenormalizedRate = ({ blocksPerDay, rate }) => - Math.pow(1 + (blocksPerDay * Number(rate)) / Number(1e18), 365) - 1, - }: CompoundSupplyTokenHelperParams) { - const multicall = this.appToolkit.getMulticall(network); - const tokenSelector = this.appToolkit.getTokenDependencySelector({ tags: { network, context: appId } }); - - const comptrollerContract = getComptrollerContract({ network, address: comptrollerAddress }); - const marketTokenAddressesRaw = await getAllMarkets({ contract: comptrollerContract, multicall }); - - const underlyings = await Promise.all( - marketTokenAddressesRaw.map(async marketTokenAddressRaw => { - const marketTokenAddress = marketTokenAddressRaw.toLowerCase(); - const contract = getTokenContract({ address: marketTokenAddress, network }); - - const underlyingAddressRaw = await getUnderlyingAddress({ contract, multicall }).catch(err => { - // if the underlying call failed, it's the compound-wrapped native token - const isCompoundWrappedNativeToken = err.message.includes('Multicall call failed for'); - if (isCompoundWrappedNativeToken) return ZERO_ADDRESS; - throw err; - }); - - const underlyingTokenAddress = underlyingAddressRaw.toLowerCase().replace(ETH_ADDR_ALIAS, ZERO_ADDRESS); - return { underlyingTokenAddress, marketTokenAddress }; - }), - ); - - const tokenDependencies = await tokenSelector - .getMany(underlyings.map(({ underlyingTokenAddress }) => ({ network, address: underlyingTokenAddress }))) - .then(deps => compact(deps)); - - const tokens = await Promise.all( - underlyings.map(async ({ underlyingTokenAddress, marketTokenAddress }) => { - const erc20TokenContract = this.contractFactory.erc20({ address: marketTokenAddress, network }); - const contract = getTokenContract({ address: marketTokenAddress, network }); - - const underlyingToken = tokenDependencies.find(v => v?.address === underlyingTokenAddress); - if (!underlyingToken) return null; - - const [symbol, decimals, supplyRaw, rateRaw, supplyRateRaw, borrowRateRaw] = await Promise.all([ - multicall.wrap(erc20TokenContract).symbol(), - multicall.wrap(erc20TokenContract).decimals(), - multicall.wrap(erc20TokenContract).totalSupply(), - getExchangeRate({ contract, multicall }), - getSupplyRate({ contract, multicall }).catch(() => 0), - getBorrowRate({ contract, multicall }).catch(() => 0), - ]); - - // Data Props - const type = ContractType.APP_TOKEN; - const supply = Number(supplyRaw) / 10 ** decimals; - const underlyingTokenDecimals = underlyingToken.decimals; - const mantissa = getExchangeRateMantissa({ tokenDecimals: decimals, underlyingTokenDecimals }); - const pricePerShare = Number(rateRaw) / 10 ** mantissa; - const price = pricePerShare * underlyingToken.price; - const liquidity = price * supply; - const tokens = [underlyingToken]; - const blocksPerDay = BLOCKS_PER_DAY[network]; - const supplyApy = getDenormalizedRate({ - blocksPerDay, - rate: supplyRateRaw, - decimals: underlyingToken.decimals, - }); - const borrowApy = getDenormalizedRate({ - blocksPerDay, - rate: borrowRateRaw, - decimals: underlyingToken.decimals, - }); - - // Display Props - const label = getDisplayLabel - ? await getDisplayLabel({ contract, multicall, underlyingToken }) - : underlyingToken.symbol; - const labelDetailed = symbol; - const secondaryLabel = buildDollarDisplayItem(underlyingToken.price); - const tertiaryLabel = `${(supplyApy * 100).toFixed(3)}% APY`; - const images = [getTokenImg(underlyingToken.address, network)]; - const balanceDisplayMode = BalanceDisplayMode.UNDERLYING; - const statsItems = [ - { label: getSupplyRateLabel(), value: buildPercentageDisplayItem(supplyApy * 100) }, - { label: 'Liquidity', value: buildDollarDisplayItem(liquidity) }, - ]; - - const token: AppTokenPosition = { - type, - address: marketTokenAddress, - network, - appId, - groupId, - symbol, - decimals, - supply, - price, - pricePerShare, - tokens, - - dataProps: { - marketName, - supplyApy, - borrowApy, - liquidity, - comptrollerAddress, - exchangeable, - }, - - displayProps: { - label, - labelDetailed, - secondaryLabel, - tertiaryLabel, - images, - statsItems, - balanceDisplayMode, - }, - }; - - return token; - }), - ); - - return _.compact(tokens); - } -} diff --git a/src/apps/compound/index.ts b/src/apps/compound/index.ts index 5278f501e..b2f02db40 100644 --- a/src/apps/compound/index.ts +++ b/src/apps/compound/index.ts @@ -2,15 +2,6 @@ export { COMPOUND_DEFINITION, CompoundAppDefinition } from './compound.definitio export { CompoundAppModule } from './compound.module'; export { CompoundContractFactory } from './contracts'; -/* Helpers */ -export { CompoundBorrowBalanceHelper } from './helper/compound.borrow.balance-helper'; -export { CompoundBorrowContractPositionHelper } from './helper/compound.borrow.contract-position-helper'; -export { CompoundClaimableBalanceHelper } from './helper/compound.claimable.balance-helper'; -export { CompoundLendingMetaHelper } from './helper/compound.lending.meta-helper'; -export { CompoundSupplyBalanceHelper } from './helper/compound.supply.balance-helper'; -export { CompoundSupplyTokenHelper } from './helper/compound.supply.token-helper'; -export { CompoundClaimableContractPositionHelper } from './helper/compound.claimable.contract-position-helper'; - /* Contracts */ export type { CompoundCToken } from './contracts'; export type { CompoundComptroller } from './contracts'; diff --git a/src/apps/curve/curve.module.ts b/src/apps/curve/curve.module.ts index 0ebc7ac8f..e5841b863 100644 --- a/src/apps/curve/curve.module.ts +++ b/src/apps/curve/curve.module.ts @@ -10,8 +10,6 @@ import { CurveAppDefinition } from './curve.definition'; import { ETHEREUM_CURVE_PROVIDERS } from './ethereum'; import { FANTOM_CURVE_PROVIDERS } from './fantom'; import { GNOSIS_CURVE_PROVIDERS } from './gnosis'; -import { CurveVotingEscrowContractPositionBalanceHelper } from './helpers/curve.voting-escrow.contract-position-balance-helper'; -import { CurveVotingEscrowContractPositionHelper } from './helpers/curve.voting-escrow.contract-position-helper'; import { OPTIMISM_CURVE_PROVIDERS } from './optimism'; import { POLYGON_CURVE_PROVIDERS } from './polygon'; @@ -28,16 +26,6 @@ import { POLYGON_CURVE_PROVIDERS } from './polygon'; ...GNOSIS_CURVE_PROVIDERS, ...OPTIMISM_CURVE_PROVIDERS, ...POLYGON_CURVE_PROVIDERS, - // Legacy Helpers - CurveVotingEscrowContractPositionHelper, - CurveVotingEscrowContractPositionBalanceHelper, - ], - exports: [ - CurveAppDefinition, - CurveContractFactory, - // Legacy Helpers - CurveVotingEscrowContractPositionHelper, - CurveVotingEscrowContractPositionBalanceHelper, ], }) export class CurveAppModule extends AbstractApp() {} diff --git a/src/apps/curve/helpers/curve.voting-escrow.contract-position-balance-helper.ts b/src/apps/curve/helpers/curve.voting-escrow.contract-position-balance-helper.ts deleted file mode 100644 index b541bbabe..000000000 --- a/src/apps/curve/helpers/curve.voting-escrow.contract-position-balance-helper.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; -import { compact, sumBy } from 'lodash'; - -import { drillBalance } from '~app-toolkit'; -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { ContractPositionBalance } from '~position/position-balance.interface'; -import { MetaType } from '~position/position.interface'; -import { Network } from '~types/network.interface'; - -import { CurveVotingEscrowContractPositionDataProps } from './curve.voting-escrow.contract-position-helper'; - -type CurveVotingEscrowContractPositionBalanceHelperParams = { - address: string; - appId: string; - groupId: string; - network: Network; - resolveContract: (opts: { network: Network; address: string }) => T; - resolveRewardContract?: (opts: { network: Network; address: string }) => V; - resolveLockedTokenBalance: (opts: { - contract: T; - multicall: IMulticallWrapper; - address: string; - }) => Promise; - resolveRewardTokenBalance?: (opts: { - contract: V; - multicall: IMulticallWrapper; - address: string; - }) => Promise; -}; - -@Injectable() -export class CurveVotingEscrowContractPositionBalanceHelper { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getBalances({ - address, - appId, - groupId, - network, - resolveContract, - resolveRewardContract, - resolveLockedTokenBalance, - resolveRewardTokenBalance, - }: CurveVotingEscrowContractPositionBalanceHelperParams): Promise { - const multicall = this.appToolkit.getMulticall(network); - const contractPositions = await this.appToolkit.getAppContractPositions( - { - network, - appId, - groupIds: [groupId], - }, - ); - - const balances = await Promise.all( - contractPositions.map(async contractPosition => { - const lockedToken = contractPosition.tokens.find(token => token.metaType === MetaType.SUPPLIED); - const rewardToken = contractPosition.tokens.find(token => token.metaType === MetaType.CLAIMABLE); - if (!lockedToken) return null; - - // Resolve escrowed token - const contract = resolveContract({ network, address: contractPosition.address }); - const lockedTokenBalanceRaw = await resolveLockedTokenBalance({ contract, multicall, address }); - const lockedTokenBalance = drillBalance(lockedToken, lockedTokenBalanceRaw.toString()); - const tokens = [lockedTokenBalance]; - - if (rewardToken && resolveRewardContract && resolveRewardTokenBalance) { - const rewardAddress = contractPosition.dataProps.rewardAddress!; - const rewardContract = resolveRewardContract({ network, address: rewardAddress }); - const rewardTokenBalanceRaw = await resolveRewardTokenBalance({ - contract: rewardContract, - multicall, - address, - }); - const rewardTokenBalance = drillBalance(rewardToken, rewardTokenBalanceRaw.toString()); - tokens.push(rewardTokenBalance); - } - - const balanceUSD = sumBy(tokens, t => t.balanceUSD); - return { ...contractPosition, tokens, balanceUSD }; - }), - ); - - return compact(balances); - } -} diff --git a/src/apps/curve/helpers/curve.voting-escrow.contract-position-helper.ts b/src/apps/curve/helpers/curve.voting-escrow.contract-position-helper.ts deleted file mode 100644 index 9de862c03..000000000 --- a/src/apps/curve/helpers/curve.voting-escrow.contract-position-helper.ts +++ /dev/null @@ -1,101 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { buildDollarDisplayItem } from '~app-toolkit/helpers/presentation/display-item.present'; -import { getImagesFromToken, getLabelFromToken } from '~app-toolkit/helpers/presentation/image.present'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { ContractType } from '~position/contract.interface'; -import { ContractPosition, MetaType } from '~position/position.interface'; -import { AppGroupsDefinition } from '~position/position.service'; -import { supplied } from '~position/position.utils'; -import { Network } from '~types/network.interface'; - -export type CurveVotingEscrowContractPositionDataProps = { - rewardAddress?: string; - liquidity: number; -}; - -type CurveVotingEscrowContractPositionHelperParams = { - appId: string; - groupId: string; - network: Network; - votingEscrowAddress: string; - votingEscrowRewardAddress?: string; - appTokenDependencies?: AppGroupsDefinition[]; - resolveContract: (opts: { network: Network; address: string }) => T; - resolveRewardContract?: (opts: { network: Network; address: string }) => V; - resolveLockedTokenAddress: (opts: { contract: T; multicall: IMulticallWrapper }) => Promise; - resolveRewardTokenAddress?: (opts: { contract: V; multicall: IMulticallWrapper }) => Promise; -}; - -export class CurveVotingEscrowContractPositionHelper { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getContractPositions({ - votingEscrowAddress, - votingEscrowRewardAddress, - appId, - groupId, - network, - appTokenDependencies = [], - resolveContract, - resolveLockedTokenAddress, - resolveRewardContract, - resolveRewardTokenAddress, - }: CurveVotingEscrowContractPositionHelperParams) { - const multicall = this.appToolkit.getMulticall(network); - const baseTokens = await this.appToolkit.getBaseTokenPrices(network); - const appTokens = await this.appToolkit.getAppTokenPositions(...appTokenDependencies); - const allTokens = [...appTokens, ...baseTokens]; - - // Resolve escrowed token - const escrowContract = resolveContract({ network, address: votingEscrowAddress }); - const escrowedTokenAddressRaw = await resolveLockedTokenAddress({ contract: escrowContract, multicall }); - const escrowedTokenAddress = escrowedTokenAddressRaw.toLowerCase(); - const escrowedToken = allTokens.find(v => v.address === escrowedTokenAddress); - if (!escrowedToken) return []; - - const escrowedTokenContract = this.appToolkit.globalContracts.erc20({ address: escrowedToken.address, network }); - const balanceOfRaw = await multicall.wrap(escrowedTokenContract).balanceOf(votingEscrowAddress); - const balanceOf = Number(balanceOfRaw) / 10 ** escrowedToken.decimals; - const liquidity = balanceOf * escrowedToken.price; - - const tokens = [supplied(escrowedToken)]; - const dataProps: CurveVotingEscrowContractPositionDataProps = { liquidity }; - - // Resolve reward token if applicable - if (resolveRewardContract && resolveRewardTokenAddress) { - const rewardContract = resolveRewardContract({ network, address: votingEscrowRewardAddress! }); - const rewardTokenAddressRaw = await resolveRewardTokenAddress({ contract: rewardContract, multicall }); - const rewardTokenAddress = rewardTokenAddressRaw.toLowerCase(); - const rewardToken = allTokens.find(v => v.address === rewardTokenAddress)!; - tokens.push({ metaType: MetaType.CLAIMABLE, ...rewardToken }); - dataProps.rewardAddress = votingEscrowRewardAddress; - } - - // Display Props - const label = `Voting Escrow ${getLabelFromToken(escrowedToken)}`; - const secondaryLabel = buildDollarDisplayItem(escrowedToken.price); - const images = getImagesFromToken(escrowedToken); - const statsItems = [ - { - label: 'Liquidity', - value: buildDollarDisplayItem(liquidity), - }, - ]; - const displayProps = { label, secondaryLabel, images, statsItems }; - - const contractPosition: ContractPosition = { - address: votingEscrowAddress, - type: ContractType.POSITION, - appId, - groupId, - network, - tokens, - dataProps, - displayProps, - }; - - return [contractPosition]; - } -} diff --git a/src/apps/curve/index.ts b/src/apps/curve/index.ts index 4508654f3..507f07fa0 100644 --- a/src/apps/curve/index.ts +++ b/src/apps/curve/index.ts @@ -1,7 +1,3 @@ export { CURVE_DEFINITION, CurveAppDefinition } from './curve.definition'; export { CurveAppModule } from './curve.module'; export { CurveContractFactory } from './contracts'; - -/* Helpers */ -export { CurveVotingEscrowContractPositionBalanceHelper } from './helpers/curve.voting-escrow.contract-position-balance-helper'; -export { CurveVotingEscrowContractPositionHelper } from './helpers/curve.voting-escrow.contract-position-helper'; diff --git a/src/apps/geist/fantom/geist.stable-debt.token-fetcher.ts b/src/apps/geist/fantom/geist.stable-debt.token-fetcher.ts index 27a02ff39..d9d36c468 100644 --- a/src/apps/geist/fantom/geist.stable-debt.token-fetcher.ts +++ b/src/apps/geist/fantom/geist.stable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class FantomGeistStableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class FantomGeistStableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0xf3b0611e2e4d2cd6ab4bb3e01ade211c3f42a8c3'; isDebt = true; diff --git a/src/apps/geist/fantom/geist.supply.token-fetcher.ts b/src/apps/geist/fantom/geist.supply.token-fetcher.ts index 618bef1a3..ad5d3e797 100644 --- a/src/apps/geist/fantom/geist.supply.token-fetcher.ts +++ b/src/apps/geist/fantom/geist.supply.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class FantomGeistSupplyTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class FantomGeistSupplyTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0xf3b0611e2e4d2cd6ab4bb3e01ade211c3f42a8c3'; isDebt = false; diff --git a/src/apps/geist/fantom/geist.variable-debt.token-fetcher.ts b/src/apps/geist/fantom/geist.variable-debt.token-fetcher.ts index a5a5a26b1..7dd313bfa 100644 --- a/src/apps/geist/fantom/geist.variable-debt.token-fetcher.ts +++ b/src/apps/geist/fantom/geist.variable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; +import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class FantomGeistVariableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class FantomGeistVariableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0xf3b0611e2e4d2cd6ab4bb3e01ade211c3f42a8c3'; isDebt = true; diff --git a/src/apps/granary-finance/ethereum/granary-finance.stable-debt.token-fetcher.ts b/src/apps/granary-finance/ethereum/granary-finance.stable-debt.token-fetcher.ts index ee3d3f081..21c69cea2 100644 --- a/src/apps/granary-finance/ethereum/granary-finance.stable-debt.token-fetcher.ts +++ b/src/apps/granary-finance/ethereum/granary-finance.stable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class EthereumGranaryFinanceStableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class EthereumGranaryFinanceStableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x33c62bc416309f010c4941163abea3725e4645bf'; isDebt = true; diff --git a/src/apps/granary-finance/ethereum/granary-finance.supply.token-fetcher.ts b/src/apps/granary-finance/ethereum/granary-finance.supply.token-fetcher.ts index 22b450bca..39ea97d1a 100644 --- a/src/apps/granary-finance/ethereum/granary-finance.supply.token-fetcher.ts +++ b/src/apps/granary-finance/ethereum/granary-finance.supply.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class EthereumGranaryFinanceSupplyTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class EthereumGranaryFinanceSupplyTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x33c62bc416309f010c4941163abea3725e4645bf'; isDebt = false; diff --git a/src/apps/granary-finance/ethereum/granary-finance.variable-debt.token-fetcher.ts b/src/apps/granary-finance/ethereum/granary-finance.variable-debt.token-fetcher.ts index 8406bdf9a..16b4e23eb 100644 --- a/src/apps/granary-finance/ethereum/granary-finance.variable-debt.token-fetcher.ts +++ b/src/apps/granary-finance/ethereum/granary-finance.variable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class EthereumGranaryFinanceVariableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class EthereumGranaryFinanceVariableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x33c62bc416309f010c4941163abea3725e4645bf'; isDebt = true; diff --git a/src/apps/granary-finance/optimism/granary-finance.stable-debt.token-fetcher.ts b/src/apps/granary-finance/optimism/granary-finance.stable-debt.token-fetcher.ts index 05a876a81..b6b4bd10f 100644 --- a/src/apps/granary-finance/optimism/granary-finance.stable-debt.token-fetcher.ts +++ b/src/apps/granary-finance/optimism/granary-finance.stable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class OptimismGranaryFinanceStableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class OptimismGranaryFinanceStableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x9546f673ef71ff666ae66d01fd6e7c6dae5a9995'; isDebt = true; diff --git a/src/apps/granary-finance/optimism/granary-finance.supply.token-fetcher.ts b/src/apps/granary-finance/optimism/granary-finance.supply.token-fetcher.ts index c3853d669..37d522680 100644 --- a/src/apps/granary-finance/optimism/granary-finance.supply.token-fetcher.ts +++ b/src/apps/granary-finance/optimism/granary-finance.supply.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class OptimismGranaryFinanceSupplyTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class OptimismGranaryFinanceSupplyTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x9546f673ef71ff666ae66d01fd6e7c6dae5a9995'; isDebt = false; diff --git a/src/apps/granary-finance/optimism/granary-finance.variable-debt.token-fetcher.ts b/src/apps/granary-finance/optimism/granary-finance.variable-debt.token-fetcher.ts index 3dc06c150..081ebd6e0 100644 --- a/src/apps/granary-finance/optimism/granary-finance.variable-debt.token-fetcher.ts +++ b/src/apps/granary-finance/optimism/granary-finance.variable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class OptimismGranaryFinanceVariableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class OptimismGranaryFinanceVariableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0x9546f673ef71ff666ae66d01fd6e7c6dae5a9995'; isDebt = true; diff --git a/src/apps/mahadao/mahadao.module.ts b/src/apps/mahadao/mahadao.module.ts index 907fb089c..0aff74ea8 100644 --- a/src/apps/mahadao/mahadao.module.ts +++ b/src/apps/mahadao/mahadao.module.ts @@ -1,20 +1,12 @@ import { Module } from '@nestjs/common'; import { AbstractApp } from '~app/app.dynamic-module'; -import { CurveVotingEscrowContractPositionBalanceHelper } from '~apps/curve/helpers/curve.voting-escrow.contract-position-balance-helper'; -import { CurveVotingEscrowContractPositionHelper } from '~apps/curve/helpers/curve.voting-escrow.contract-position-helper'; import { MahadaoContractFactory } from './contracts'; import { EthereumMahadaoLockerContractPositionFetcher } from './ethereum/mahadao.locker.contract-position-fetcher'; import { MahadaoAppDefinition } from './mahadao.definition'; @Module({ - providers: [ - MahadaoAppDefinition, - MahadaoContractFactory, - CurveVotingEscrowContractPositionBalanceHelper, - CurveVotingEscrowContractPositionHelper, - EthereumMahadaoLockerContractPositionFetcher, - ], + providers: [MahadaoAppDefinition, MahadaoContractFactory, EthereumMahadaoLockerContractPositionFetcher], }) export class MahadaoAppModule extends AbstractApp() {} diff --git a/src/apps/maker/maker.module.ts b/src/apps/maker/maker.module.ts index e5d0cd099..2180f96fe 100644 --- a/src/apps/maker/maker.module.ts +++ b/src/apps/maker/maker.module.ts @@ -14,6 +14,5 @@ import { MakerAppDefinition } from './maker.definition'; EthereumMakerGovernanceContractPositionFetcher, EthereumMakerVaultContractPositionFetcher, ], - exports: [MakerContractFactory], }) export class MakerAppModule extends AbstractApp() {} diff --git a/src/apps/naos/naos.module.ts b/src/apps/naos/naos.module.ts index b06aa4ff8..26a13b7e3 100644 --- a/src/apps/naos/naos.module.ts +++ b/src/apps/naos/naos.module.ts @@ -8,6 +8,5 @@ import { NaosAppDefinition } from './naos.definition'; @Module({ providers: [NaosAppDefinition, NaosContractFactory, EthereumNaosFarmContractPositionFetcher], - exports: [NaosContractFactory], }) export class NaosAppModule extends AbstractApp() {} diff --git a/src/apps/nereus-finance/avalanche/nereus-finance.stable-debt.token-fetcher.ts b/src/apps/nereus-finance/avalanche/nereus-finance.stable-debt.token-fetcher.ts index a6c0029e8..cb8ed0e87 100644 --- a/src/apps/nereus-finance/avalanche/nereus-finance.stable-debt.token-fetcher.ts +++ b/src/apps/nereus-finance/avalanche/nereus-finance.stable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class AvalancheNereusFinanceStableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class AvalancheNereusFinanceStableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0xec090929fbc1b285fc9b3c8ebb92fbc62f01d804'; isDebt = true; diff --git a/src/apps/nereus-finance/avalanche/nereus-finance.supply.token-fetcher.ts b/src/apps/nereus-finance/avalanche/nereus-finance.supply.token-fetcher.ts index 1c0432169..5595c618e 100644 --- a/src/apps/nereus-finance/avalanche/nereus-finance.supply.token-fetcher.ts +++ b/src/apps/nereus-finance/avalanche/nereus-finance.supply.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class AvalancheNereusFinanceSupplyTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class AvalancheNereusFinanceSupplyTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0xec090929fbc1b285fc9b3c8ebb92fbc62f01d804'; isDebt = false; diff --git a/src/apps/nereus-finance/avalanche/nereus-finance.variable-debt.token-fetcher.ts b/src/apps/nereus-finance/avalanche/nereus-finance.variable-debt.token-fetcher.ts index f90e193e6..766a3a1cf 100644 --- a/src/apps/nereus-finance/avalanche/nereus-finance.variable-debt.token-fetcher.ts +++ b/src/apps/nereus-finance/avalanche/nereus-finance.variable-debt.token-fetcher.ts @@ -1,15 +1,15 @@ import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; import { AaveV2AToken } from '~apps/aave-v2/contracts'; import { - AaveV2LendingTemplateTokenFetcher, + AaveV2LendingTokenFetcher, AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() -export class AvalancheNereusFinanceVariableDebtTokenFetcher extends AaveV2LendingTemplateTokenFetcher { +export class AvalancheNereusFinanceVariableDebtTokenFetcher extends AaveV2LendingTokenFetcher { groupLabel = 'Lending'; providerAddress = '0xec090929fbc1b285fc9b3c8ebb92fbc62f01d804'; isDebt = true; diff --git a/src/apps/olympus/olympus.module.ts b/src/apps/olympus/olympus.module.ts index 0beb8f536..e7ce7ac23 100644 --- a/src/apps/olympus/olympus.module.ts +++ b/src/apps/olympus/olympus.module.ts @@ -44,12 +44,5 @@ import { PolygonOlympusGOhmTokenFetcher } from './polygon/olympus.g-ohm.token-fe OlympusBondContractPositionHelper, OlympusBondV1ContractPositionBalanceHelper, ], - exports: [ - OlympusAppDefinition, - OlympusContractFactory, - OlympusBondContractPositionHelper, - OlympusBondV1ContractPositionBalanceHelper, - OlympusBridgeTokenHelper, - ], }) export class OlympusAppModule extends AbstractApp() {} diff --git a/src/apps/pool-together-v3/pool-together-v3.module.ts b/src/apps/pool-together-v3/pool-together-v3.module.ts index b5a0cbe3e..557fc78c2 100644 --- a/src/apps/pool-together-v3/pool-together-v3.module.ts +++ b/src/apps/pool-together-v3/pool-together-v3.module.ts @@ -46,6 +46,5 @@ import { PoolTogetherV3AppDefinition } from './pool-together-v3.definition'; PolygonPoolTogetherV3SponsorshipTokenFetcher, PolygonPoolTogetherV3TicketTokenFetcher, ], - exports: [PoolTogetherV3ApiPrizePoolRegistry], }) export class PoolTogetherV3AppModule extends AbstractApp() {} diff --git a/src/apps/sturdy/ethereum/sturdy.stable-debt.token-fetcher.ts b/src/apps/sturdy/ethereum/sturdy.stable-debt.token-fetcher.ts index 595e8c151..78f243f66 100644 --- a/src/apps/sturdy/ethereum/sturdy.stable-debt.token-fetcher.ts +++ b/src/apps/sturdy/ethereum/sturdy.stable-debt.token-fetcher.ts @@ -5,7 +5,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() diff --git a/src/apps/sturdy/ethereum/sturdy.supply.token-fetcher.ts b/src/apps/sturdy/ethereum/sturdy.supply.token-fetcher.ts index 9b743ead8..07b03eaf5 100644 --- a/src/apps/sturdy/ethereum/sturdy.supply.token-fetcher.ts +++ b/src/apps/sturdy/ethereum/sturdy.supply.token-fetcher.ts @@ -5,7 +5,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() diff --git a/src/apps/sturdy/ethereum/sturdy.variable-debt.token-fetcher.ts b/src/apps/sturdy/ethereum/sturdy.variable-debt.token-fetcher.ts index 8a68d7765..07d2c5b1e 100644 --- a/src/apps/sturdy/ethereum/sturdy.variable-debt.token-fetcher.ts +++ b/src/apps/sturdy/ethereum/sturdy.variable-debt.token-fetcher.ts @@ -5,7 +5,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() diff --git a/src/apps/sturdy/fantom/sturdy.stable-debt.token-fetcher.ts b/src/apps/sturdy/fantom/sturdy.stable-debt.token-fetcher.ts index 27617f443..407e72ad1 100644 --- a/src/apps/sturdy/fantom/sturdy.stable-debt.token-fetcher.ts +++ b/src/apps/sturdy/fantom/sturdy.stable-debt.token-fetcher.ts @@ -5,7 +5,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() diff --git a/src/apps/sturdy/fantom/sturdy.supply.token-fetcher.ts b/src/apps/sturdy/fantom/sturdy.supply.token-fetcher.ts index 332a56f02..936ce6aaa 100644 --- a/src/apps/sturdy/fantom/sturdy.supply.token-fetcher.ts +++ b/src/apps/sturdy/fantom/sturdy.supply.token-fetcher.ts @@ -5,7 +5,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() diff --git a/src/apps/sturdy/fantom/sturdy.variable-debt.token-fetcher.ts b/src/apps/sturdy/fantom/sturdy.variable-debt.token-fetcher.ts index 0d924ec37..a1cf5f0ad 100644 --- a/src/apps/sturdy/fantom/sturdy.variable-debt.token-fetcher.ts +++ b/src/apps/sturdy/fantom/sturdy.variable-debt.token-fetcher.ts @@ -5,7 +5,7 @@ import { AaveV2LendingTokenDataProps, AaveV2ReserveApyData, AaveV2ReserveTokenAddressesData, -} from '~apps/aave-v2/helpers/aave-v2.lending.template.token-fetcher'; +} from '~apps/aave-v2/common/aave-v2.lending.token-fetcher'; import { GetDisplayPropsParams } from '~position/template/app-token.template.types'; @PositionTemplate() diff --git a/src/apps/synthetix/helpers/synthetix.single-staking-farm-contract-position-balance-helper.ts b/src/apps/synthetix/helpers/synthetix.single-staking-farm-contract-position-balance-helper.ts deleted file mode 100644 index 8a6c218a6..000000000 --- a/src/apps/synthetix/helpers/synthetix.single-staking-farm-contract-position-balance-helper.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { - SingleStakingContractStrategy, - SingleStakingRewardTokenBalanceStrategy, - SingleStakingStakedTokenBalanceStrategy, -} from '~app-toolkit/helpers/balance/single-staking-farm.contract-position-balance-helper'; -import { Network } from '~types/network.interface'; - -import { SynthetixContractFactory, SynthetixRewards } from '../contracts'; - -export type SynthetixSingleStakingFarmContractPositionBalanceHelperParams = { - address: string; - network: Network; - appId: string; - groupId: string; - resolveContract?: SingleStakingContractStrategy; - resolveStakedTokenBalance?: SingleStakingStakedTokenBalanceStrategy; - resolveRewardTokenBalances?: SingleStakingRewardTokenBalanceStrategy; -}; - -@Injectable() -export class SynthetixSingleStakingFarmContractPositionBalanceHelper { - constructor( - @Inject(APP_TOOLKIT) - private readonly appToolkit: IAppToolkit, - @Inject(SynthetixContractFactory) - private readonly synthetixContractFactory: SynthetixContractFactory, - ) {} - - getBalances({ - address, - appId, - groupId, - network, - resolveContract = opts => this.synthetixContractFactory.synthetixRewards(opts), - resolveStakedTokenBalance = ({ contract, address, multicall }) => multicall.wrap(contract).balanceOf(address), - resolveRewardTokenBalances = ({ contract, address, multicall }) => multicall.wrap(contract).earned(address), - }: SynthetixSingleStakingFarmContractPositionBalanceHelperParams) { - return this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances({ - address, - appId, - groupId, - network, - resolveContract, - resolveStakedTokenBalance, - resolveRewardTokenBalances, - }); - } -} diff --git a/src/apps/synthetix/helpers/synthetix.single-staking-farm-contract-position-helper.ts b/src/apps/synthetix/helpers/synthetix.single-staking-farm-contract-position-helper.ts deleted file mode 100644 index 5bb410b91..000000000 --- a/src/apps/synthetix/helpers/synthetix.single-staking-farm-contract-position-helper.ts +++ /dev/null @@ -1,68 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { - SingleStakingFarmDefinition, - SingleStakingFarmResolveIsActiveParams, - SingleStakingFarmResolveRoisParams, -} from '~app-toolkit/helpers/position/single-staking-farm.contract-position-helper'; -import { AppGroupsDefinition } from '~position/position.service'; -import { Network } from '~types/network.interface'; - -import { SynthetixContractFactory, SynthetixRewards } from '../contracts'; - -import { SynthetixSingleStakingIsActiveStrategy } from './synthetix.single-staking.is-active-strategy'; -import { SynthetixSingleStakingRoiStrategy } from './synthetix.single-staking.roi-strategy'; - -export type SynthetixSingleStakingFarmContractPositionHelperParams = { - network: Network; - appId: string; - groupId: string; - resolveIsActive?: SingleStakingFarmResolveIsActiveParams; - resolveRois?: SingleStakingFarmResolveRoisParams; - farmDefinitions: SingleStakingFarmDefinition[]; - dependencies?: AppGroupsDefinition[]; -}; - -@Injectable() -export class SynthetixSingleStakingFarmContractPositionHelper { - constructor( - @Inject(SynthetixContractFactory) - private readonly contractFactory: SynthetixContractFactory, - @Inject(SynthetixSingleStakingIsActiveStrategy) - private readonly isActiveStrategy: SynthetixSingleStakingIsActiveStrategy, - @Inject(SynthetixSingleStakingRoiStrategy) - private readonly roiStrategy: SynthetixSingleStakingRoiStrategy, - @Inject(APP_TOOLKIT) - private readonly appToolkit: IAppToolkit, - ) {} - - getContractPositions({ - farmDefinitions, - dependencies = [], - resolveIsActive = this.defaultIsActive(), - resolveRois = this.defaultRois(), - ...opts - }: SynthetixSingleStakingFarmContractPositionHelperParams) { - return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions({ - ...opts, - dependencies, - resolveFarmDefinitions: async () => farmDefinitions, - resolveFarmContract: ({ network, address }) => this.contractFactory.synthetixRewards({ network, address }), - resolveIsActive, - resolveRois, - }); - } - - defaultIsActive(): SingleStakingFarmResolveIsActiveParams { - return this.isActiveStrategy.build({ - resolvePeriodFinish: ({ contract, multicall }) => multicall.wrap(contract).periodFinish(), - }); - } - - defaultRois(): SingleStakingFarmResolveRoisParams { - return this.roiStrategy.build({ - resolveRewardRates: ({ contract, multicall }) => multicall.wrap(contract).rewardRate(), - }); - } -} diff --git a/src/apps/synthetix/helpers/synthetix.single-staking.is-active-strategy.ts b/src/apps/synthetix/helpers/synthetix.single-staking.is-active-strategy.ts deleted file mode 100644 index ea6a88a59..000000000 --- a/src/apps/synthetix/helpers/synthetix.single-staking.is-active-strategy.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; - -import { SingleStakingFarmResolveIsActiveParams } from '~app-toolkit/helpers/position/single-staking-farm.contract-position-helper'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; - -export type SynthetixSingleStakingIsActiveStrategyParams = { - resolvePeriodFinish: (opts: { contract: T; multicall: IMulticallWrapper }) => Promise; -}; - -@Injectable() -export class SynthetixSingleStakingIsActiveStrategy { - build({ - resolvePeriodFinish, - }: SynthetixSingleStakingIsActiveStrategyParams): SingleStakingFarmResolveIsActiveParams { - return async ({ contract, multicall }) => { - const periodFinish = await resolvePeriodFinish({ multicall, contract }); - const now = Math.floor(Date.now() / 1000) - 60 * 60; - return Number(periodFinish) > now; - }; - } -} diff --git a/src/apps/synthetix/helpers/synthetix.single-staking.roi-strategy.ts b/src/apps/synthetix/helpers/synthetix.single-staking.roi-strategy.ts deleted file mode 100644 index 26a1db5c3..000000000 --- a/src/apps/synthetix/helpers/synthetix.single-staking.roi-strategy.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; -import { isArray, sum } from 'lodash'; - -import { SingleStakingFarmResolveRoisParams } from '~app-toolkit/helpers/position/single-staking-farm.contract-position-helper'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; - -export type SynthetixSingleStakingIsActiveStrategyParams = { - resolveRewardRates: (opts: { contract: T; multicall: IMulticallWrapper }) => Promise; -}; - -@Injectable() -export class SynthetixSingleStakingRoiStrategy { - build({ - resolveRewardRates, - }: SynthetixSingleStakingIsActiveStrategyParams): SingleStakingFarmResolveRoisParams { - return async ({ contract, multicall, rewardTokens, liquidity }) => { - const rewardRates = await resolveRewardRates({ contract, multicall }).then(v => (isArray(v) ? v : [v])); - - const dailyRewardRatesUSD = rewardRates.map((rewardRateRaw, i) => { - if (!rewardTokens[i]) return 0; - const rewardRate = Number(rewardRateRaw) / 10 ** rewardTokens[i].decimals; - return rewardRate * 86400 * rewardTokens[i].price; - }); - - const dailyRewardUSD = sum(dailyRewardRatesUSD); - const dailyROI = (dailyRewardUSD + liquidity) / liquidity - 1; - const weeklyROI = dailyROI * 7; - const yearlyROI = dailyROI * 365; - - return { dailyROI, weeklyROI, yearlyROI }; - }; - } -} diff --git a/src/apps/synthetix/index.ts b/src/apps/synthetix/index.ts index 0bed2e785..23b80f00f 100644 --- a/src/apps/synthetix/index.ts +++ b/src/apps/synthetix/index.ts @@ -2,11 +2,6 @@ export { SYNTHETIX_DEFINITION, SynthetixAppDefinition } from './synthetix.defini export { SynthetixAppModule } from './synthetix.module'; export { SynthetixContractFactory } from './contracts'; -export { SynthetixSingleStakingFarmContractPositionBalanceHelper } from './helpers/synthetix.single-staking-farm-contract-position-balance-helper'; -export { SynthetixSingleStakingFarmContractPositionHelper } from './helpers/synthetix.single-staking-farm-contract-position-helper'; -export { SynthetixSingleStakingIsActiveStrategy } from './helpers/synthetix.single-staking.is-active-strategy'; -export { SynthetixSingleStakingRoiStrategy } from './helpers/synthetix.single-staking.roi-strategy'; - export type { SynthetixAddressResolver } from './contracts'; export type { SynthetixNetworkToken } from './contracts'; export type { SynthetixRewards } from './contracts'; diff --git a/src/apps/synthetix/synthetix.module.ts b/src/apps/synthetix/synthetix.module.ts index 006adbb93..a07954140 100644 --- a/src/apps/synthetix/synthetix.module.ts +++ b/src/apps/synthetix/synthetix.module.ts @@ -10,10 +10,6 @@ import { EthereumSynthetixMintrContractPositionFetcher } from './ethereum/synthe import { EthereumSynthetixPositionPresenter } from './ethereum/synthetix.position-presenter'; import { EthereumSynthetixSnxTokenFetcher } from './ethereum/synthetix.snx.token-fetcher'; import { EthereumSynthetixSynthTokenFetcher } from './ethereum/synthetix.synth.token-fetcher'; -import { SynthetixSingleStakingFarmContractPositionBalanceHelper } from './helpers/synthetix.single-staking-farm-contract-position-balance-helper'; -import { SynthetixSingleStakingFarmContractPositionHelper } from './helpers/synthetix.single-staking-farm-contract-position-helper'; -import { SynthetixSingleStakingIsActiveStrategy } from './helpers/synthetix.single-staking.is-active-strategy'; -import { SynthetixSingleStakingRoiStrategy } from './helpers/synthetix.single-staking.roi-strategy'; import { OptimismSynthetixLoanContractPositionFetcher } from './optimism/synthetix.loan.contract-position-fetcher'; import { OptimismSynthetixMintrContractPositionFetcher } from './optimism/synthetix.mintr.contract-position-fetcher'; import { OptimismSynthetixPositionPresenter } from './optimism/synthetix.position-presenter'; @@ -25,10 +21,6 @@ import { SynthetixAppDefinition } from './synthetix.definition'; providers: [ SynthetixAppDefinition, SynthetixContractFactory, - SynthetixSingleStakingIsActiveStrategy, - SynthetixSingleStakingRoiStrategy, - SynthetixSingleStakingFarmContractPositionHelper, - SynthetixSingleStakingFarmContractPositionBalanceHelper, SynthetixMintrSnxHoldersCache, // Ethereum EthereumSynthetixFarmContractPositionFetcher, @@ -44,12 +36,5 @@ import { SynthetixAppDefinition } from './synthetix.definition'; OptimismSynthetixLoanContractPositionFetcher, OptimismSynthetixPositionPresenter, ], - exports: [ - SynthetixContractFactory, - SynthetixSingleStakingIsActiveStrategy, - SynthetixSingleStakingRoiStrategy, - SynthetixSingleStakingFarmContractPositionHelper, - SynthetixSingleStakingFarmContractPositionBalanceHelper, - ], }) export class SynthetixAppModule extends AbstractApp() {} diff --git a/src/apps/uniswap-v2/helpers/uniswap-v2.on-chain.pool-token-address-strategy.ts b/src/apps/uniswap-v2/helpers/uniswap-v2.on-chain.pool-token-address-strategy.ts deleted file mode 100644 index fcb5ed02a..000000000 --- a/src/apps/uniswap-v2/helpers/uniswap-v2.on-chain.pool-token-address-strategy.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { BigNumberish } from 'ethers'; -import _ from 'lodash'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; - -import { UniswapFactory, UniswapPair } from '../contracts'; - -import { UniswapV2PoolTokenHelperParams } from './uniswap-v2.pool.token-helper'; - -type GetPoolAddressListParams = { - resolvePoolsLength: (opts: { multicall: IMulticallWrapper; factoryContract: T }) => Promise; - resolvePoolAddress: (opts: { - multicall: IMulticallWrapper; - factoryContract: T; - poolIndex: number; - }) => Promise; - resolvePoolAddressIsValid?: (opts: { multicall: IMulticallWrapper; poolContract: V }) => Promise; -}; - -@Injectable() -export class UniswapV2OnChainPoolTokenAddressStrategy { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - build({ - resolvePoolsLength, - resolvePoolAddress, - resolvePoolAddressIsValid, - }: GetPoolAddressListParams): UniswapV2PoolTokenHelperParams['resolvePoolTokenAddresses'] { - return async ({ factoryAddress, network, resolveFactoryContract, resolvePoolContract }) => { - const multicall = this.appToolkit.getMulticall(network); - - const factoryContract = resolveFactoryContract({ address: factoryAddress, network }); - const poolsLength = await resolvePoolsLength({ multicall, factoryContract }); - - const poolAddresses = await Promise.all( - _.range(0, Number(poolsLength)).map(async poolIndex => { - const poolAddressRaw = await resolvePoolAddress({ multicall, factoryContract, poolIndex }); - const poolAddress = poolAddressRaw.toLowerCase(); - if (!resolvePoolAddressIsValid) return poolAddress; - - const poolContract = resolvePoolContract({ address: poolAddress, network }); - const isValid = await resolvePoolAddressIsValid({ multicall, poolContract }); - return isValid ? poolAddress : null; - }), - ); - - return _.compact(poolAddresses); - }; - } -} diff --git a/src/apps/uniswap-v2/helpers/uniswap-v2.on-chain.token-derivation-strategy.ts b/src/apps/uniswap-v2/helpers/uniswap-v2.on-chain.token-derivation-strategy.ts deleted file mode 100644 index daf0b36da..000000000 --- a/src/apps/uniswap-v2/helpers/uniswap-v2.on-chain.token-derivation-strategy.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { compact, isNil, isNull, keyBy } from 'lodash'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { ZERO_ADDRESS } from '~app-toolkit/constants/address'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { ContractType } from '~position/contract.interface'; -import { BaseToken } from '~position/token.interface'; - -import { UniswapFactory, UniswapPair } from '../contracts'; - -import { UniswapV2PoolTokenHelperParams } from './uniswap-v2.pool.token-helper'; - -type GetDerivedPriceParams = { - priceDerivationWhitelist: string[]; - resolvePoolAddress: (opts: { - multicall: IMulticallWrapper; - factoryContract: T; - token0: string; - token1: string; - }) => Promise; -}; - -@Injectable() -export class UniswapV2OnChainTokenDerivationStrategy { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - build({ - priceDerivationWhitelist, - resolvePoolAddress, - }: GetDerivedPriceParams): UniswapV2PoolTokenHelperParams['resolveDerivedUnderlyingToken'] { - return async ({ - factoryAddress, - network, - tokenAddress, - resolvePoolUnderlyingTokenAddresses, - resolveFactoryContract, - resolvePoolContract, - resolvePoolReserves, - tokenDependencySelector, - }) => { - const baseTokenMatches = await tokenDependencySelector - .getMany(priceDerivationWhitelist.map(address => ({ network, address }))) - .then(tokens => compact(tokens)) - .then(tokens => keyBy(tokens, ({ address }) => address)); - - const multicall = this.appToolkit.getMulticall(network); - const factoryContract = resolveFactoryContract({ address: factoryAddress, network }); - - const contract = this.appToolkit.globalContracts.erc20({ address: tokenAddress, network }); - const [symbol, decimals] = await Promise.all([ - multicall - .wrap(contract) - .symbol() - .catch(() => null), - multicall - .wrap(contract) - .decimals() - .catch(() => null), - ]); - - // For non-ERC20 tokens - if (isNull(symbol) || isNull(decimals)) { - return null; - } - - const baseToken: BaseToken = { - type: ContractType.BASE_TOKEN, - address: tokenAddress, - network: network, - price: 0, - symbol: symbol, - decimals: decimals, - }; - - const derivationResults = await Promise.all( - priceDerivationWhitelist.map(async knownTokenAddress => { - const poolAddress = await resolvePoolAddress({ - factoryContract, - multicall, - token0: tokenAddress, - token1: knownTokenAddress, - }); - - if (poolAddress === ZERO_ADDRESS) return null; - - const knownToken = baseTokenMatches[knownTokenAddress]; - if (!knownToken) return null; - - const poolContract = resolvePoolContract({ address: poolAddress, network }); - const tokensRaw = await resolvePoolUnderlyingTokenAddresses({ multicall, poolContract }); - const reserves = await resolvePoolReserves({ multicall, poolContract }); - const tokens = tokensRaw.map(t => t.toLowerCase()); - - const unknownIndex = tokens.findIndex(t => t === tokenAddress); - const knownIndex = 1 - unknownIndex; - - const knownReserve = Number(reserves[knownIndex]) / 10 ** knownToken.decimals; - const unknownReserve = Number(reserves[unknownIndex]) / 10 ** decimals; - const knownLiquidity = knownToken.price * knownReserve; - if (knownLiquidity < 1) return null; // Minimum liquidity check - - const price = knownLiquidity / unknownReserve; - return { ...baseToken, price }; - }), - ); - - const validDerivationResult = derivationResults.find(dr => !isNil(dr)); - - return validDerivationResult ?? baseToken; - }; - } -} diff --git a/src/apps/uniswap-v2/helpers/uniswap-v2.pool.token-helper.ts b/src/apps/uniswap-v2/helpers/uniswap-v2.pool.token-helper.ts deleted file mode 100644 index d096f9c7b..000000000 --- a/src/apps/uniswap-v2/helpers/uniswap-v2.pool.token-helper.ts +++ /dev/null @@ -1,246 +0,0 @@ -import { Inject } from '@nestjs/common'; -import BigNumber from 'bignumber.js'; -import { BigNumberish } from 'ethers'; -import { compact } from 'lodash'; -import { sortBy } from 'lodash'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { - buildDollarDisplayItem, - buildPercentageDisplayItem, -} from '~app-toolkit/helpers/presentation/display-item.present'; -import { getImagesFromToken } from '~app-toolkit/helpers/presentation/image.present'; -import { IMulticallWrapper } from '~multicall/multicall.interface'; -import { ContractType } from '~position/contract.interface'; -import { AppTokenPosition, Token } from '~position/position.interface'; -import { TokenDependencySelector } from '~position/selectors/token-dependency-selector.interface'; -import { BaseToken } from '~position/token.interface'; -import { Network } from '~types/network.interface'; - -import { UniswapFactory, UniswapPair } from '../contracts'; - -export type UniswapV2PoolTokenDataProps = { - liquidity: number; - fee: number; - volume: number; - volumeChangePercentage: number; - isBlocked: boolean; -}; - -type ResolvePoolVolumesResponse = { poolAddress: string; volumeChangeUSD: number; volumeChangePercentage: number }[]; - -type ResolvePoolTokenAddressesResponse = string[]; - -export type UniswapV2PoolTokenHelperParams = { - network: Network; - appId: string; - groupId: string; - factoryAddress: string; - fee?: number; - minLiquidity?: number; - hiddenTokens?: string[]; - blockedPools?: string[]; - priceDerivationWhitelist?: string[]; - resolveFactoryContract(opts: { address: string; network: Network }): T; - resolvePoolContract(opts: { address: string; network: Network }): V; - resolvePoolTokenAddresses: (opts: { - appId: string; - network: Network; - factoryAddress: string; - resolveFactoryContract(opts: { address: string; network: Network }): T; - resolvePoolContract(opts: { address: string; network: Network }): V; - }) => Promise; - resolveDerivedUnderlyingToken?(opts: { - appId: string; - network: Network; - factoryAddress: string; - tokenAddress: string; - tokenDependencySelector: TokenDependencySelector; - resolveFactoryContract(opts: { address: string; network: Network }): T; - resolvePoolContract(opts: { address: string; network: Network }): V; - resolvePoolUnderlyingTokenAddresses(opts: { - multicall: IMulticallWrapper; - poolContract: V; - }): Promise<[string, string]>; - resolvePoolReserves(opts: { multicall: IMulticallWrapper; poolContract: V }): Promise<[BigNumberish, BigNumberish]>; - }): Promise; - resolvePoolVolumes?: (opts: { - appId: string; - network: Network; - resolveFactoryContract(opts: { address: string; network: Network }): T; - resolvePoolContract(opts: { address: string; network: Network }): V; - }) => Promise; - resolvePoolTokenSymbol(opts: { multicall: IMulticallWrapper; poolContract: V }): Promise; - resolvePoolTokenSupply(opts: { multicall: IMulticallWrapper; poolContract: V }): Promise; - resolvePoolUnderlyingTokenAddresses(opts: { - multicall: IMulticallWrapper; - poolContract: V; - }): Promise<[string, string]>; - resolvePoolReserves(opts: { multicall: IMulticallWrapper; poolContract: V }): Promise<[BigNumberish, BigNumberish]>; - resolveTokenDisplayPrefix?: (symbol: string) => string; - resolveTokenDisplaySymbol?: (token: Token) => string; -}; - -export class UniswapV2PoolTokenHelper { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - async getTokens({ - network, - appId, - groupId, - factoryAddress, - fee = 0.3, - minLiquidity = 0, - hiddenTokens = [], - blockedPools = [], - resolveFactoryContract, - resolvePoolContract, - resolveDerivedUnderlyingToken, - resolvePoolTokenAddresses, - resolvePoolTokenSymbol, - resolvePoolTokenSupply, - resolvePoolUnderlyingTokenAddresses, - resolvePoolReserves, - resolveTokenDisplaySymbol = token => token.symbol, - resolvePoolVolumes = async () => [], - }: UniswapV2PoolTokenHelperParams) { - const multicall = this.appToolkit.getMulticall(network); - const tokenSelector = this.appToolkit.getTokenDependencySelector({ tags: { network, context: appId } }); - - const poolAddresses: ResolvePoolTokenAddressesResponse = await resolvePoolTokenAddresses({ - appId, - network, - factoryAddress, - resolveFactoryContract, - resolvePoolContract, - }); - - const poolVolumes: ResolvePoolVolumesResponse = await resolvePoolVolumes({ - appId, - network, - resolveFactoryContract, - resolvePoolContract, - }).catch(() => []); - - // NB: Token addresses are resolved first because of a Multicall batch size of 250 - // This allows DL to use its max batch size of 1000+ in the next loop - const poolTokensWithAddresses = await Promise.all( - poolAddresses.map(async address => { - const poolContract = resolvePoolContract({ address, network }); - const [token0AddressRaw, token1AddressRaw] = await resolvePoolUnderlyingTokenAddresses({ - multicall, - poolContract, - }); - - const token0Address = token0AddressRaw.toLowerCase(); - const token1Address = token1AddressRaw.toLowerCase(); - if (hiddenTokens.includes(token0Address) || hiddenTokens.includes(token1Address)) return null; - - return { address, token0Address, token1Address }; - }), - ); - - const poolTokens = await Promise.all( - compact(poolTokensWithAddresses).map(async ({ address, token0Address, token1Address }) => { - const type = ContractType.APP_TOKEN; - const poolContract = resolvePoolContract({ address, network }); - - const resolvedTokens = await Promise.all( - [token0Address, token1Address].map(async tokenAddress => { - const underlyingToken = await tokenSelector.getOne({ network, address: tokenAddress }); - - if (underlyingToken) return underlyingToken; - if (!resolveDerivedUnderlyingToken) return null; - - return resolveDerivedUnderlyingToken({ - appId, - factoryAddress, - network, - tokenDependencySelector: tokenSelector, - resolveFactoryContract, - resolvePoolContract, - resolvePoolReserves, - resolvePoolUnderlyingTokenAddresses, - tokenAddress, - }); - }), - ); - - const tokens = compact(resolvedTokens); - if (tokens.length !== resolvedTokens.length) return null; - - // Retrieve pool reserves and pool token supply - const [symbol, supplyRaw, reservesRaw] = await Promise.all([ - resolvePoolTokenSymbol({ multicall, poolContract }), - resolvePoolTokenSupply({ multicall, poolContract }), - resolvePoolReserves({ multicall, poolContract }), - ]); - - // Data Props - const decimals = 18; - const reservesBN = reservesRaw.map((r, i) => new BigNumber(r.toString()).div(10 ** tokens[i].decimals)); - const reserves = reservesBN.map(v => v.toNumber()); - const liquidity = tokens[0].price * reserves[0] + tokens[1].price * reserves[1]; - const reservePercentages = tokens.map((t, i) => reserves[i] * (t.price / liquidity)); - const supply = Number(supplyRaw) / 10 ** decimals; - const price = liquidity / supply; - const pricePerShare = reserves.map(r => r / supply); - const volume = poolVolumes.find(v => v.poolAddress === address)?.volumeChangeUSD ?? 0; - const volumeChangePercentage = poolVolumes.find(v => v.poolAddress === address)?.volumeChangePercentage ?? 0; - const isBlocked = blockedPools.includes(address); - const ratio = reservePercentages.map(p => `${Math.round(p * 100)}%`).join(' / '); - const projectedYearlyVolume = volume * 365; - const apy = (projectedYearlyVolume * 100) / liquidity; - - // Display Props - const label = `${resolveTokenDisplaySymbol(tokens[0])} / ${resolveTokenDisplaySymbol(tokens[1])}`; - const secondaryLabel = ratio; - const images = tokens.map(v => getImagesFromToken(v)).flat(); - const statsItems = [ - { label: 'Volume', value: buildDollarDisplayItem(volume) }, - { label: 'APY', value: buildPercentageDisplayItem(apy) }, - { label: 'Fee', value: buildPercentageDisplayItem(fee) }, - { label: 'Reserves', value: reserves.map(v => (v < 0.01 ? '<0.01' : v.toFixed(2))).join(' / ') }, - { label: 'Liquidity', value: buildDollarDisplayItem(liquidity) }, - { label: 'Ratio', value: ratio }, - ]; - - const poolToken: AppTokenPosition = { - type, - address, - network, - appId, - groupId, - symbol, - decimals, - supply, - price, - pricePerShare, - tokens, - - displayProps: { - label, - secondaryLabel, - images, - statsItems, - }, - - dataProps: { - liquidity, - fee, - volume, - volumeChangePercentage, - isBlocked, - }, - }; - - return poolToken; - }), - ); - - return sortBy( - compact(poolTokens).filter(t => t.dataProps.liquidity > minLiquidity), - t => -t!.dataProps.liquidity, - ); - } -} diff --git a/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-token-address-strategy.ts b/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-token-address-strategy.ts deleted file mode 100644 index 5dc25478a..000000000 --- a/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-token-address-strategy.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { gql } from 'graphql-request'; -import { range, uniq } from 'lodash'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { Cache } from '~cache/cache.decorator'; - -import { UniswapFactory, UniswapPair } from '../contracts'; - -import { UniswapV2PoolTokenHelperParams } from './uniswap-v2.pool.token-helper'; - -const DEFAULT_POOLS_QUERY = gql` - query getPools($first: Int, $skip: Int, $orderBy: Pair_orderBy) { - pairs(first: $first, skip: $skip, orderBy: $orderBy, orderDirection: desc) { - id - } - } -`; - -const DEFAULT_POOLS_BY_ID_QUERY = gql` - query getPoolsById($ids: [ID!]) { - pairs(where: { id_in: $ids }) { - id - } - } -`; - -type PoolsResponse = { - pairs?: { - id: string; - }[]; -}; - -type UniswapV2TheGraphPoolTokenAddressStrategyParams = { - subgraphUrl: string; - first: number; - orderBy?: string; - requiredPools?: string[]; - poolsQuery?: string; - poolsByIdQuery?: string; -}; - -@Injectable() -export class UniswapV2TheGraphPoolTokenAddressStrategy { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - @Cache({ - key: (subgraphUrl: string) => { - const [namespace, name] = subgraphUrl.split('/').slice(-2); - return `studio:uniswap-v2-fork:pool-token-addresses:${namespace}:${name}`; - }, - ttl: 5 * 60, - }) - async getPoolAddresses( - subgraphUrl: string, - first: number, - orderBy: string, - requiredPools: string[], - poolsQuery: string, - poolsByIdQuery: string, - ) { - const graphHelper = this.appToolkit.helpers.theGraphHelper; - - const chunks = await Promise.all( - range(0, first, 1000).map(skip => { - const count = Math.min(1000, first - skip); - return graphHelper.request({ - endpoint: subgraphUrl, - query: poolsQuery, - variables: { first: count, skip, orderBy }, - }); - }), - ); - - const poolsData = chunks.flat(); - const poolsByIdData = await graphHelper.request({ - endpoint: subgraphUrl, - query: poolsByIdQuery, - variables: { ids: requiredPools }, - }); - - const pools = poolsData.map(v => v.pairs ?? []).flat(); - const poolsById = poolsByIdData.pairs ?? []; - - const poolIds = [...pools, ...poolsById].map(v => v.id.toLowerCase()); - const uniquepoolIds = uniq(poolIds); - return uniquepoolIds; - } - - build({ - subgraphUrl, - first, - orderBy = 'reserveUSD', - requiredPools = [], - poolsQuery = DEFAULT_POOLS_QUERY, - poolsByIdQuery = DEFAULT_POOLS_BY_ID_QUERY, - }: UniswapV2TheGraphPoolTokenAddressStrategyParams): UniswapV2PoolTokenHelperParams< - T, - V - >['resolvePoolTokenAddresses'] { - return () => this.getPoolAddresses(subgraphUrl, first, orderBy, requiredPools, poolsQuery, poolsByIdQuery); - } -} diff --git a/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-token-balance-helper.ts b/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-token-balance-helper.ts deleted file mode 100644 index e5541bf77..000000000 --- a/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-token-balance-helper.ts +++ /dev/null @@ -1,214 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { gql } from 'graphql-request'; -import { keyBy } from 'lodash'; - -import { drillBalance } from '~app-toolkit'; -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { - buildDollarDisplayItem, - buildPercentageDisplayItem, -} from '~app-toolkit/helpers/presentation/display-item.present'; -import { getTokenImg } from '~app-toolkit/helpers/presentation/image.present'; -import { ContractType } from '~position/contract.interface'; -import { AppTokenPosition } from '~position/position.interface'; -import { BaseToken } from '~position/token.interface'; -import { Network } from '~types/network.interface'; - -import { UniswapV2ContractFactory } from '../contracts'; - -import { UniswapV2PoolTokenDataProps } from './uniswap-v2.pool.token-helper'; - -type UniswapV2GetBalancesParams = { - address: string; - network: Network; - appId: string; - groupId: string; - subgraphUrl: string; - symbolPrefix: string; - fee?: number; - overrideDecimalsForTokens?: string[]; -}; - -type BalanceData = { - user?: { - liquidityPositions: { - liquidityTokenBalance: string; - pair: { - id: string; - reserve0: string; - reserve1: string; - reserveUSD: string; - token0: { - id: string; - decimals: string; - symbol: string; - }; - token1: { - id: string; - decimals: string; - symbol: string; - }; - totalSupply: string; - }; - }[]; - }; -}; - -const GET_BALANCE_QUERY = gql` - query getBalances($address: String!) { - user(id: $address) { - liquidityPositions { - liquidityTokenBalance - pair { - id - totalSupply - reserveUSD - reserve0 - reserve1 - token0 { - id - decimals - symbol - } - token1 { - id - decimals - symbol - } - } - } - } - } -`; - -const rename = (token: string) => { - const renameTo: Record = { - 'yDAI+yUSDC+yUSDT+yTUSD': 'Y Curve', - 'yyDAI+yUSDC+yUSDT+yTUSD': 'yUSD', - REPv2: 'REP', - '': 'AAVE', - }; - if (renameTo[token]) return renameTo[token]; - else return token; -}; - -@Injectable() -export class UniswapV2TheGraphPoolTokenBalanceHelper { - constructor( - @Inject(UniswapV2ContractFactory) private readonly contractFactory: UniswapV2ContractFactory, - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - ) {} - - async getBalances({ - address, - network, - appId, - groupId, - subgraphUrl, - symbolPrefix, - fee = 0.003, - overrideDecimalsForTokens = [], - }: UniswapV2GetBalancesParams) { - const multicall = this.appToolkit.getMulticall(network); - const prices = await this.appToolkit.getBaseTokenPrices(network); - const pricesByAddress = keyBy(prices, p => p.address); - const graphHelper = this.appToolkit.helpers.theGraphHelper; - const data = await graphHelper.requestGraph({ - endpoint: subgraphUrl, - query: GET_BALANCE_QUERY, - variables: { address: address.toLowerCase() }, - }); - - const balances = await Promise.all( - (data.user?.liquidityPositions ?? []).map(async lp => { - const pairAddress = lp.pair.id; - const contract = this.contractFactory.erc20({ address: pairAddress, network }); - const balanceRaw = await multicall.wrap(contract).balanceOf(address); - - // Resolve the tokens either from our base tokens or from data from TheGraph - const tokens: BaseToken[] = [lp.pair.token0, lp.pair.token1].map(tokenData => { - if (pricesByAddress[tokenData.id]) return pricesByAddress[tokenData.id]; - const overrideDecimals = overrideDecimalsForTokens.includes(tokenData.id); - const decimals = overrideDecimals ? 18 : +tokenData.decimals; - const symbol = rename(tokenData.symbol === 'WETH' ? 'ETH' : tokenData.symbol); - return { type: ContractType.BASE_TOKEN, address, network, symbol, decimals, price: 0 }; - }); - - // Resolve the reserves. In some cases, these need to be denormalized from TheGraph data - const reserves = [Number(lp.pair.reserve0), Number(lp.pair.reserve1)].map((reserve, i) => { - if (!overrideDecimalsForTokens.includes(tokens[i].address)) return reserve; - return reserve / 10 ** tokens[i].decimals; - }); - - // Resolve token spot prices - if (tokens[0].price && !tokens[1].price) { - // If we have the price of one of the tokens, we can infer the price of the other via the reserves - tokens[1].price = (tokens[0].price * reserves[0]) / reserves[1]; - } else if (!tokens[0].price && tokens[1].price) { - // Same can be said for the opposite token - tokens[0].price = (tokens[1].price * reserves[1]) / reserves[0]; - } else if (!tokens[0].price && !tokens[1].price) { - // In all other cases, rely on the price of the tokens as they stand in the pool. - const liquidity = Number(lp.pair.reserveUSD); - tokens[0].price = liquidity / reserves[0] / 2; - tokens[1].price = liquidity / reserves[1] / 2; - } - - const decimals = 18; - const liquidity = tokens[0].price * reserves[0] + tokens[1].price * reserves[1]; - const reservePercentages = tokens.map((t, i) => reserves[i] * (t.price / liquidity)); - const supply = Number(lp.pair.totalSupply); - const price = liquidity / supply; - const pricePerShare = [reserves[0] / supply, reserves[1] / supply]; - const volume = 0; - const volumeChangePercentage = 0; - const isBlocked = false; - const ratio = reservePercentages.map(p => `${Math.round(p * 100)}%`).join(' / '); - - // Display Props - const label = `${tokens[0].symbol} / ${tokens[1].symbol}`; - const secondaryLabel = ratio; - const images = [getTokenImg(tokens[0].address, network), getTokenImg(tokens[1].address, network)]; - const statsItems = [ - { label: 'Liquidity', value: buildDollarDisplayItem(liquidity) }, - { label: 'Volume', value: buildDollarDisplayItem(volume) }, - { label: 'Fee', value: buildPercentageDisplayItem(fee) }, - { label: 'Ratio', value: ratio }, - ]; - - const poolToken: AppTokenPosition = { - type: ContractType.APP_TOKEN, - address: pairAddress, - symbol: symbolPrefix, - decimals, - supply, - network, - appId, - groupId, - pricePerShare, - price, - tokens, - - dataProps: { - liquidity, - fee, - volume, - volumeChangePercentage, - isBlocked, - }, - - displayProps: { - label, - secondaryLabel, - images, - statsItems, - }, - }; - - return drillBalance(poolToken, balanceRaw.toString()); - }), - ); - - return balances; - } -} diff --git a/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-volume-strategy.ts b/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-volume-strategy.ts deleted file mode 100644 index c403cd419..000000000 --- a/src/apps/uniswap-v2/helpers/uniswap-v2.the-graph.pool-volume-strategy.ts +++ /dev/null @@ -1,214 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import { gql } from 'graphql-request'; -import { uniqBy } from 'lodash'; - -import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; -import { BLOCKS_PER_DAY } from '~app-toolkit/constants/blocks'; - -import { UniswapFactory, UniswapPair } from '../contracts'; - -import { UniswapV2PoolTokenHelperParams } from './uniswap-v2.pool.token-helper'; - -type LastBlockSyncedResponse = { - _meta: { - block: { - number: number; - }; - }; -}; - -type PoolVolumesResponse = { - pairs: { - id: string; - volumeUSD: string; - untrackedVolumeUSD: string; - }[]; -}; - -type SinglePoolVolumeResponse = { - pair: { - id: string; - volumeUSD: string; - untrackedVolumeUSD: string; - }; -}; - -const DEFAULT_LAST_BLOCK_SYNCED_ON_GRAPH_QUERY = gql` - { - _meta { - block { - number - } - } - } -`; - -// @TODO where: { reserveUSD_gte: $minLiquidity } -const DEFAULT_POOL_VOLUMES_QUERY = gql` - query getCurrentPairVolumes($first: Int) { - pairs(first: $first, skip: 0, orderBy: reserveUSD, orderDirection: desc) { - id - volumeUSD - untrackedVolumeUSD - } - } -`; - -const DEFAULT_POOL_VOLUMES_AT_BLOCK_QUERY = gql` - query getCurrentPairVolumes($first: Int, $block: Int) { - pairs(first: $first, skip: 0, orderBy: reserveUSD, orderDirection: desc, block: { number: $block }) { - id - volumeUSD - untrackedVolumeUSD - } - } -`; - -const DEFAULT_POOL_VOLUMES_BY_ID_QUERY = gql` - query getPastPairVolumesByID($ids: [String]) { - pairs(where: { id_in: $ids }) { - id - volumeUSD - untrackedVolumeUSD - } - } -`; - -const DEFAULT_POOL_VOLUMES_BY_ID_AT_BLOCK_QUERY = gql` - query getPastPairVolumesByID($ids: [String], $block: Int) { - pairs(where: { id_in: $ids }, block: { number: $block }) { - id - volumeUSD - untrackedVolumeUSD - } - } -`; - -const DEFAULT_SINGLE_POOL_VOLUME_AT_BLOCK_QUERY = gql` - query getSinglePairVolume($id: String, $block: Int) { - pair(id: $id, block: { number: $block }) { - id - volumeUSD - untrackedVolumeUSD - } - } -`; - -type UniswapV2TheGraphPoolVolumeStrategyParams = { - subgraphUrl: string; - first: number; - blocksPerDay?: number; - requiredPools?: string[]; - lastBlockSyncedOnGraphQuery?: string; - poolVolumesQuery?: string; - poolVolumesAtBlockQuery?: string; - poolVolumesByIdQuery?: string; - poolVolumesByIdAtBlockQuery?: string; - singlePoolVolumeAtBlockQuery?: string; -}; - -@Injectable() -export class UniswapV2TheGraphPoolVolumeStrategy { - constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {} - - build({ - subgraphUrl, - first, - blocksPerDay = 0, - requiredPools = [], - lastBlockSyncedOnGraphQuery = DEFAULT_LAST_BLOCK_SYNCED_ON_GRAPH_QUERY, - poolVolumesQuery = DEFAULT_POOL_VOLUMES_QUERY, - poolVolumesAtBlockQuery = DEFAULT_POOL_VOLUMES_AT_BLOCK_QUERY, - poolVolumesByIdQuery = DEFAULT_POOL_VOLUMES_BY_ID_QUERY, - poolVolumesByIdAtBlockQuery = DEFAULT_POOL_VOLUMES_BY_ID_AT_BLOCK_QUERY, - singlePoolVolumeAtBlockQuery = DEFAULT_SINGLE_POOL_VOLUME_AT_BLOCK_QUERY, - }: UniswapV2TheGraphPoolVolumeStrategyParams): UniswapV2PoolTokenHelperParams['resolvePoolVolumes'] { - return async ({ network }) => { - // Get block from 1 day ago - const provider = this.appToolkit.getNetworkProvider(network); - const block = await provider.getBlockNumber(); - const block1DayAgo = block - (blocksPerDay ?? BLOCKS_PER_DAY[network]); - - const graphHelper = this.appToolkit.helpers.theGraphHelper; - - // Get last block synced on graph; if the graph is not caught up to yesterday, exit early - const graphMetaData = await graphHelper.request({ - endpoint: subgraphUrl, - query: lastBlockSyncedOnGraphQuery, - }); - - const blockNumberLastSynced = graphMetaData._meta.block.number; - if (block1DayAgo > blockNumberLastSynced) return []; - - // Retrieve volume data from TheGraph (@TODO Cache this) - const [volumeData, volumeData1DayAgo, volumeByIDData, volumeByIDData1DayAgo] = await Promise.all([ - graphHelper.request({ - endpoint: subgraphUrl, - query: poolVolumesQuery, - variables: { first }, - }), - graphHelper.request({ - endpoint: subgraphUrl, - query: poolVolumesAtBlockQuery, - variables: { first, block: block1DayAgo }, - }), - graphHelper.request({ - endpoint: subgraphUrl, - query: poolVolumesByIdQuery, - variables: { ids: requiredPools }, - }), - graphHelper.request({ - endpoint: subgraphUrl, - query: poolVolumesByIdAtBlockQuery, - variables: { ids: requiredPools, block: block1DayAgo }, - }), - ]); - - // Merge all volume data for today and merge all volume data for yesterday - const allVolumeData = uniqBy([...volumeData.pairs, ...volumeByIDData.pairs], p => p.id); - const allVolumeData1DayAgo = uniqBy([...volumeData1DayAgo.pairs, ...volumeByIDData1DayAgo.pairs], p => p.id); - - const poolVolumes = await Promise.all( - allVolumeData.map(async pairVolumeToday => { - // Find the matching volume entry from yesterday - let poolVolumeYesterday = allVolumeData1DayAgo.find(p => p.id === pairVolumeToday.id); - - // Some pairs move in and out of the top requested pairs, so retrieve the missing pair-volumes by ID individually - if (!poolVolumeYesterday) { - poolVolumeYesterday = await graphHelper - .request({ - endpoint: subgraphUrl, - query: singlePoolVolumeAtBlockQuery, - variables: { - id: pairVolumeToday.id, - block, - }, - }) - .then(v => v.pair); - } - - // Calculate volume chnage between yesterday and today wherever applicable - let volumeChangeUSD: number, volumeChangePercentage: number; - if (pairVolumeToday?.volumeUSD && poolVolumeYesterday?.volumeUSD) { - const volumeUSDToday = Number(pairVolumeToday.volumeUSD); - const volumeUSDYesterday = Number(poolVolumeYesterday.volumeUSD); - volumeChangeUSD = volumeUSDToday - volumeUSDYesterday; - volumeChangePercentage = Math.abs(volumeChangeUSD / volumeUSDYesterday); - } else if (pairVolumeToday?.untrackedVolumeUSD && poolVolumeYesterday?.untrackedVolumeUSD) { - const volumeUSDToday = Number(pairVolumeToday.untrackedVolumeUSD); - const volumeUSDYesterday = Number(poolVolumeYesterday.untrackedVolumeUSD); - volumeChangeUSD = volumeUSDToday - volumeUSDYesterday; - volumeChangePercentage = Math.abs(volumeChangeUSD / volumeUSDYesterday); - } else { - volumeChangeUSD = 0; - volumeChangePercentage = 0; - } - - return { poolAddress: pairVolumeToday.id, volumeChangeUSD, volumeChangePercentage }; - }), - ); - - return poolVolumes; - }; - } -} diff --git a/src/apps/uniswap-v2/index.ts b/src/apps/uniswap-v2/index.ts index e26546c83..778ec5005 100644 --- a/src/apps/uniswap-v2/index.ts +++ b/src/apps/uniswap-v2/index.ts @@ -2,16 +2,5 @@ export { UNISWAP_V2_DEFINITION, UniswapV2AppDefinition } from './uniswap-v2.defi export { UniswapV2AppModule } from './uniswap-v2.module'; export { UniswapV2ContractFactory } from './contracts'; -export { UniswapV2OnChainPoolTokenAddressStrategy } from './helpers/uniswap-v2.on-chain.pool-token-address-strategy'; -export { UniswapV2OnChainTokenDerivationStrategy } from './helpers/uniswap-v2.on-chain.token-derivation-strategy'; -export { UniswapV2PoolTokenHelper } from './helpers/uniswap-v2.pool.token-helper'; -export { UniswapV2TheGraphPoolTokenAddressStrategy } from './helpers/uniswap-v2.the-graph.pool-token-address-strategy'; -export { UniswapV2TheGraphPoolTokenBalanceHelper } from './helpers/uniswap-v2.the-graph.pool-token-balance-helper'; -export { UniswapV2TheGraphPoolVolumeStrategy } from './helpers/uniswap-v2.the-graph.pool-volume-strategy'; - export type { UniswapFactory } from './contracts'; export type { UniswapPair } from './contracts'; -export type { - UniswapV2PoolTokenDataProps, - UniswapV2PoolTokenHelperParams, -} from './helpers/uniswap-v2.pool.token-helper'; diff --git a/src/apps/uniswap-v2/uniswap-v2.module.ts b/src/apps/uniswap-v2/uniswap-v2.module.ts index e25a661c6..5fe4d3199 100644 --- a/src/apps/uniswap-v2/uniswap-v2.module.ts +++ b/src/apps/uniswap-v2/uniswap-v2.module.ts @@ -4,35 +4,9 @@ import { AbstractApp } from '~app/app.dynamic-module'; import { UniswapV2ContractFactory } from './contracts'; import { EthereumUniswapV2PoolTokenFetcher } from './ethereum/uniswap-v2.pool.token-fetcher'; -import { UniswapV2OnChainPoolTokenAddressStrategy } from './helpers/uniswap-v2.on-chain.pool-token-address-strategy'; -import { UniswapV2OnChainTokenDerivationStrategy } from './helpers/uniswap-v2.on-chain.token-derivation-strategy'; -import { UniswapV2PoolTokenHelper } from './helpers/uniswap-v2.pool.token-helper'; -import { UniswapV2TheGraphPoolTokenAddressStrategy } from './helpers/uniswap-v2.the-graph.pool-token-address-strategy'; -import { UniswapV2TheGraphPoolTokenBalanceHelper } from './helpers/uniswap-v2.the-graph.pool-token-balance-helper'; -import { UniswapV2TheGraphPoolVolumeStrategy } from './helpers/uniswap-v2.the-graph.pool-volume-strategy'; import { UniswapV2AppDefinition } from './uniswap-v2.definition'; @Module({ - providers: [ - UniswapV2AppDefinition, - UniswapV2ContractFactory, - EthereumUniswapV2PoolTokenFetcher, - // Helpers - UniswapV2PoolTokenHelper, - UniswapV2OnChainPoolTokenAddressStrategy, - UniswapV2OnChainTokenDerivationStrategy, - UniswapV2TheGraphPoolTokenAddressStrategy, - UniswapV2TheGraphPoolVolumeStrategy, - UniswapV2TheGraphPoolTokenBalanceHelper, - ], - exports: [ - UniswapV2ContractFactory, - UniswapV2PoolTokenHelper, - UniswapV2OnChainPoolTokenAddressStrategy, - UniswapV2OnChainTokenDerivationStrategy, - UniswapV2TheGraphPoolTokenAddressStrategy, - UniswapV2TheGraphPoolVolumeStrategy, - UniswapV2TheGraphPoolTokenBalanceHelper, - ], + providers: [UniswapV2AppDefinition, UniswapV2ContractFactory, EthereumUniswapV2PoolTokenFetcher], }) export class UniswapV2AppModule extends AbstractApp() {} diff --git a/src/apps/uniswap-v3/uniswap-v3.module.ts b/src/apps/uniswap-v3/uniswap-v3.module.ts index 02822ed28..311af508d 100644 --- a/src/apps/uniswap-v3/uniswap-v3.module.ts +++ b/src/apps/uniswap-v3/uniswap-v3.module.ts @@ -20,6 +20,5 @@ import { UniswapV3AppDefinition } from './uniswap-v3.definition'; OptimismUniswapV3LiquidityContractPositionFetcher, PolygonUniswapV3LiquidityContractPositionFetcher, ], - exports: [UniswapV3ContractFactory], }) export class UniswapV3AppModule extends AbstractApp() {} diff --git a/src/apps/yearn/yearn.module.ts b/src/apps/yearn/yearn.module.ts index 83f809fc8..77b76148c 100644 --- a/src/apps/yearn/yearn.module.ts +++ b/src/apps/yearn/yearn.module.ts @@ -30,6 +30,5 @@ import { YearnAppDefinition } from './yearn.definition'; // Arbitrum ArbitrumYearnV2VaultTokenFetcher, ], - exports: [YearnContractFactory], }) export class YearnAppModule extends AbstractApp() {} diff --git a/src/apps/yield-yak/yield-yak.module.ts b/src/apps/yield-yak/yield-yak.module.ts index ceb37535e..9313a33a2 100644 --- a/src/apps/yield-yak/yield-yak.module.ts +++ b/src/apps/yield-yak/yield-yak.module.ts @@ -14,6 +14,5 @@ import { YieldYakAppDefinition } from './yield-yak.definition'; AvalancheYieldyakVaultTokenFetcher, AvalancheYieldyakFarmContractPositionFetcher, ], - exports: [YieldYakAppDefinition, YieldYakContractFactory], }) export class YieldYakAppModule extends AbstractApp() {}