From b722434ec15b3bdc5e786edf4a343724817460fb Mon Sep 17 00:00:00 2001 From: William Poulin Date: Wed, 21 Dec 2022 14:49:27 -0500 Subject: [PATCH] fix(sushiswap-bentobox): Migrate to template (#1968) * fix(sushiswap-bentobox): Migration to template * feat(sushiswap-bentobox): Add bentobox vaults on avalanche and fantom --- .../sushiswap-bentobox.balance-fetcher.ts | 34 ------ ...entobox.vault.contract-position-fetcher.ts | 33 ++---- ...entobox.vault.contract-position-fetcher.ts | 10 ++ .../sushiswap-bentobox.balance-fetcher.ts | 34 ------ ...entobox.vault.contract-position-fetcher.ts | 33 ++---- ...ushiswap-bentobox.vault-tokens-resolver.ts | 62 ++++++++++ ...entobox.vault.contract-position-fetcher.ts | 78 +++++++++++++ .../sushiswap-bentobox.balance-fetcher.ts | 34 ------ ...entobox.vault.contract-position-fetcher.ts | 34 ++---- ...entobox.vault.contract-position-fetcher.ts | 10 ++ ....vault.contract-position-balance-helper.ts | 32 ------ ...bentobox.vault.contract-position-helper.ts | 107 ------------------ src/apps/sushiswap-bentobox/index.ts | 3 - .../sushiswap-bentobox.balance-fetcher.ts | 34 ------ ...entobox.vault.contract-position-fetcher.ts | 34 ++---- .../sushiswap-bentobox.definition.ts | 2 + .../sushiswap-bentobox.module.ts | 31 ++--- 17 files changed, 200 insertions(+), 405 deletions(-) delete mode 100644 src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.balance-fetcher.ts create mode 100644 src/apps/sushiswap-bentobox/avalanche/sushiswap-bentobox.vault.contract-position-fetcher.ts delete mode 100644 src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.balance-fetcher.ts create mode 100644 src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault-tokens-resolver.ts create mode 100644 src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault.contract-position-fetcher.ts delete mode 100644 src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.balance-fetcher.ts create mode 100644 src/apps/sushiswap-bentobox/fantom/sushiswap-bentobox.vault.contract-position-fetcher.ts delete mode 100644 src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-balance-helper.ts delete mode 100644 src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-helper.ts delete mode 100644 src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.balance-fetcher.ts diff --git a/src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.balance-fetcher.ts b/src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.balance-fetcher.ts deleted file mode 100644 index 5a5c7ad67..000000000 --- a/src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.balance-fetcher.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { Register } from '~app-toolkit/decorators'; -import { presentBalanceFetcherResponse } from '~app-toolkit/helpers/presentation/balance-fetcher-response.present'; -import { BalanceFetcher } from '~balance/balance-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { SushiSwapBentoBoxContractPositionBalanceHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-balance-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const network = Network.ARBITRUM_MAINNET; - -@Register.BalanceFetcher(SUSHISWAP_BENTOBOX_DEFINITION.id, network) -export class ArbitrumSushiSwapBentoBoxBalanceFetcher implements BalanceFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionBalanceHelper) - private readonly balanceHelper: SushiSwapBentoBoxContractPositionBalanceHelper, - ) {} - - async getBalances(address: string) { - const balances = await this.balanceHelper.getBalances({ - address, - network, - bentoBoxAddress: '0x74c764d41b77dbbb4fe771dab1939b00b146894a', - }); - - return presentBalanceFetcherResponse([ - { - label: 'SushiSwap BentoBox', - assets: balances, - }, - ]); - } -} diff --git a/src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.vault.contract-position-fetcher.ts b/src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.vault.contract-position-fetcher.ts index f97d9e750..a718d5122 100644 --- a/src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.vault.contract-position-fetcher.ts +++ b/src/apps/sushiswap-bentobox/arbitrum/sushiswap-bentobox.vault.contract-position-fetcher.ts @@ -1,29 +1,10 @@ -import { Inject } from '@nestjs/common'; +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { Register } from '~app-toolkit/decorators'; -import { PositionFetcher } from '~position/position-fetcher.interface'; -import { ContractPosition } from '~position/position.interface'; -import { Network } from '~types/network.interface'; +import { SushiswapBentoboxVaultContractPositionFetcher } from '../common/sushiswap-bentobox.vault.contract-position-fetcher'; -import { SushiSwapBentoBoxContractPositionHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const appId = SUSHISWAP_BENTOBOX_DEFINITION.id; -const groupId = SUSHISWAP_BENTOBOX_DEFINITION.groups.vault.id; -const network = Network.ARBITRUM_MAINNET; - -@Register.ContractPositionFetcher({ appId, groupId, network }) -export class ArbitrumSushiSwapBentoBoxContractPositionFetcher implements PositionFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionHelper) - private readonly positionHelper: SushiSwapBentoBoxContractPositionHelper, - ) {} - - async getPositions() { - return this.positionHelper.getPositions({ - bentoBoxAddress: '0x74c764d41b77dbbb4fe771dab1939b00b146894a', - network, - subgraphUrl: 'https://api.thegraph.com/subgraphs/name/sushiswap/arbitrum-bentobox', - }); - } +@PositionTemplate() +export class ArbitrumSushiSwapBentoBoxContractPositionFetcher extends SushiswapBentoboxVaultContractPositionFetcher { + groupLabel = 'BentoBox'; + subgraphUrl = 'https://api.thegraph.com/subgraphs/name/sushiswap/bentobox-arbitrum'; + bentoboxAddress = '0x74c764d41b77dbbb4fe771dab1939b00b146894a'; } diff --git a/src/apps/sushiswap-bentobox/avalanche/sushiswap-bentobox.vault.contract-position-fetcher.ts b/src/apps/sushiswap-bentobox/avalanche/sushiswap-bentobox.vault.contract-position-fetcher.ts new file mode 100644 index 000000000..e83b14db1 --- /dev/null +++ b/src/apps/sushiswap-bentobox/avalanche/sushiswap-bentobox.vault.contract-position-fetcher.ts @@ -0,0 +1,10 @@ +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; + +import { SushiswapBentoboxVaultContractPositionFetcher } from '../common/sushiswap-bentobox.vault.contract-position-fetcher'; + +@PositionTemplate() +export class AvalancheSushiSwapBentoBoxContractPositionFetcher extends SushiswapBentoboxVaultContractPositionFetcher { + groupLabel = 'BentoBox'; + subgraphUrl = 'https://api.thegraph.com/subgraphs/name/sushiswap/bentobox-avalanche'; + bentoboxAddress = '0x0711b6026068f736bae6b213031fce978d48e026'; +} diff --git a/src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.balance-fetcher.ts b/src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.balance-fetcher.ts deleted file mode 100644 index 4f3280942..000000000 --- a/src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.balance-fetcher.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { Register } from '~app-toolkit/decorators'; -import { presentBalanceFetcherResponse } from '~app-toolkit/helpers/presentation/balance-fetcher-response.present'; -import { BalanceFetcher } from '~balance/balance-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { SushiSwapBentoBoxContractPositionBalanceHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-balance-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const network = Network.BINANCE_SMART_CHAIN_MAINNET; - -@Register.BalanceFetcher(SUSHISWAP_BENTOBOX_DEFINITION.id, network) -export class BscSushiSwapBentoBoxBalanceFetcher implements BalanceFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionBalanceHelper) - private readonly balanceHelper: SushiSwapBentoBoxContractPositionBalanceHelper, - ) {} - - async getBalances(address: string) { - const balances = await this.balanceHelper.getBalances({ - address, - network, - bentoBoxAddress: '0xf5bce5077908a1b7370b9ae04adc565ebd643966', - }); - - return presentBalanceFetcherResponse([ - { - label: 'SushiSwap BentoBox', - assets: balances, - }, - ]); - } -} diff --git a/src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.vault.contract-position-fetcher.ts b/src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.vault.contract-position-fetcher.ts index 539b76110..41ac1d099 100644 --- a/src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.vault.contract-position-fetcher.ts +++ b/src/apps/sushiswap-bentobox/binance-smart-chain/sushiswap-bentobox.vault.contract-position-fetcher.ts @@ -1,29 +1,10 @@ -import { Inject } from '@nestjs/common'; +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { Register } from '~app-toolkit/decorators'; -import { PositionFetcher } from '~position/position-fetcher.interface'; -import { ContractPosition } from '~position/position.interface'; -import { Network } from '~types/network.interface'; +import { SushiswapBentoboxVaultContractPositionFetcher } from '../common/sushiswap-bentobox.vault.contract-position-fetcher'; -import { SushiSwapBentoBoxContractPositionHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const appId = SUSHISWAP_BENTOBOX_DEFINITION.id; -const groupId = SUSHISWAP_BENTOBOX_DEFINITION.groups.vault.id; -const network = Network.BINANCE_SMART_CHAIN_MAINNET; - -@Register.ContractPositionFetcher({ appId, groupId, network }) -export class BscSushiSwapBentoBoxContractPositionFetcher implements PositionFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionHelper) - private readonly positionHelper: SushiSwapBentoBoxContractPositionHelper, - ) {} - - async getPositions() { - return this.positionHelper.getPositions({ - bentoBoxAddress: '0xf5bce5077908a1b7370b9ae04adc565ebd643966', - network, - subgraphUrl: 'https://api.thegraph.com/subgraphs/name/sushiswap/bsc-bentobox', - }); - } +@PositionTemplate() +export class BinanceSmartChainSushiSwapBentoBoxContractPositionFetcher extends SushiswapBentoboxVaultContractPositionFetcher { + groupLabel = 'BentoBox'; + subgraphUrl = 'https://api.thegraph.com/subgraphs/name/sushiswap/bentobox-bsc'; + bentoboxAddress = '0xf5bce5077908a1b7370b9ae04adc565ebd643966'; } diff --git a/src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault-tokens-resolver.ts b/src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault-tokens-resolver.ts new file mode 100644 index 000000000..1dd764e44 --- /dev/null +++ b/src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault-tokens-resolver.ts @@ -0,0 +1,62 @@ +import { Inject, Injectable } from '@nestjs/common'; +import { gql } from 'graphql-request'; + +import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; +import { Cache } from '~cache/cache.decorator'; +import { Network } from '~types/network.interface'; + +import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; + +export type UnipilotVaultDefinition = { + address: string; + token0Address: string; + token1Address: string; + feeTier: string; + token0Symbol: string; + token1Symbol: string; + strategyId?: string; + totalLockedToken0: string; + totalLockedToken1: string; +}; + +type TokensResponse = { + tokens: { + id: string; + }[]; +}; + +const ALL_TOKENS_QUERY = gql` + { + tokens(first: 500) { + id + } + } +`; + +@Injectable() +export class SushiswapBentoboxVaultTokensResolver { + constructor(@Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit) {} + + @Cache({ + key: _network => `studio:${SUSHISWAP_BENTOBOX_DEFINITION.id}:${_network}:vault-data`, + ttl: 5 * 60, // 5 minutes + }) + private async getVaultTokensData(subgraphUrl: string, _network: Network) { + const data = await this.appToolkit.helpers.theGraphHelper.request({ + endpoint: subgraphUrl, + query: ALL_TOKENS_QUERY, + }); + + return data.tokens; + } + + async getVaultTokens(subgraphUrl: string, network: Network) { + const vaultTokenData = await this.getVaultTokensData(subgraphUrl, network); + + const vaultTokens = vaultTokenData.map(token => { + return token.id; + }); + + return vaultTokens; + } +} diff --git a/src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault.contract-position-fetcher.ts b/src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault.contract-position-fetcher.ts new file mode 100644 index 000000000..f9b181c92 --- /dev/null +++ b/src/apps/sushiswap-bentobox/common/sushiswap-bentobox.vault.contract-position-fetcher.ts @@ -0,0 +1,78 @@ +import { Inject } from '@nestjs/common'; +import { BigNumberish } from 'ethers'; + +import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface'; +import { getLabelFromToken } from '~app-toolkit/helpers/presentation/image.present'; +import { MetaType } from '~position/position.interface'; +import { ContractPositionTemplatePositionFetcher } from '~position/template/contract-position.template.position-fetcher'; +import { + GetDisplayPropsParams, + GetTokenBalancesParams, + GetTokenDefinitionsParams, +} from '~position/template/contract-position.template.types'; + +import { SushiswapBentobox, SushiswapBentoboxContractFactory } from '../contracts'; + +import { SushiswapBentoboxVaultTokensResolver } from './sushiswap-bentobox.vault-tokens-resolver'; + +export type SushiswapBentoboxVaultDefinition = { + address: string; + underlyingTokenAddress: string; +}; + +export abstract class SushiswapBentoboxVaultContractPositionFetcher extends ContractPositionTemplatePositionFetcher { + abstract subgraphUrl: string; + abstract bentoboxAddress: string; + + constructor( + @Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit, + @Inject(SushiswapBentoboxContractFactory) private readonly contractFactory: SushiswapBentoboxContractFactory, + @Inject(SushiswapBentoboxVaultTokensResolver) + private readonly vaultTokenResolver: SushiswapBentoboxVaultTokensResolver, + ) { + super(appToolkit); + } + + async getDefinitions(): Promise { + const bentoboxTokens = await this.vaultTokenResolver.getVaultTokens(this.subgraphUrl, this.network); + + const vaultDefinitons = bentoboxTokens.map(underlyingTokenAddress => { + return { + address: this.bentoboxAddress, + underlyingTokenAddress, + }; + }); + + return vaultDefinitons; + } + + async getTokenDefinitions({ + definition, + }: GetTokenDefinitionsParams) { + return [ + { + metaType: MetaType.SUPPLIED, + address: definition.underlyingTokenAddress, + network: this.network, + }, + ]; + } + + getContract(address: string): SushiswapBentobox { + return this.contractFactory.sushiswapBentobox({ network: this.network, address }); + } + + async getLabel({ contractPosition }: GetDisplayPropsParams): Promise { + return `${getLabelFromToken(contractPosition.tokens[0])} Deposit`; + } + + async getTokenBalancesPerPosition({ + address, + contract, + contractPosition, + }: GetTokenBalancesParams): Promise { + const balance = await contract.balanceOf(contractPosition.tokens[0].address, address); + + return [balance]; + } +} diff --git a/src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.balance-fetcher.ts b/src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.balance-fetcher.ts deleted file mode 100644 index f11ea340a..000000000 --- a/src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.balance-fetcher.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { Register } from '~app-toolkit/decorators'; -import { presentBalanceFetcherResponse } from '~app-toolkit/helpers/presentation/balance-fetcher-response.present'; -import { BalanceFetcher } from '~balance/balance-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { SushiSwapBentoBoxContractPositionBalanceHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-balance-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const network = Network.ETHEREUM_MAINNET; - -@Register.BalanceFetcher(SUSHISWAP_BENTOBOX_DEFINITION.id, network) -export class EthereumSushiSwapBentoBoxBalanceFetcher implements BalanceFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionBalanceHelper) - private readonly balanceHelper: SushiSwapBentoBoxContractPositionBalanceHelper, - ) {} - - async getBalances(address: string) { - const balances = await this.balanceHelper.getBalances({ - address, - network, - bentoBoxAddress: '0xf5bce5077908a1b7370b9ae04adc565ebd643966', - }); - - return presentBalanceFetcherResponse([ - { - label: 'SushiSwap BentoBox', - assets: balances, - }, - ]); - } -} diff --git a/src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.vault.contract-position-fetcher.ts b/src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.vault.contract-position-fetcher.ts index 7b7dcf903..b0bb60f2b 100644 --- a/src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.vault.contract-position-fetcher.ts +++ b/src/apps/sushiswap-bentobox/ethereum/sushiswap-bentobox.vault.contract-position-fetcher.ts @@ -1,30 +1,10 @@ -import { Inject } from '@nestjs/common'; +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { Register } from '~app-toolkit/decorators'; -import { PositionFetcher } from '~position/position-fetcher.interface'; -import { ContractPosition } from '~position/position.interface'; -import { Network } from '~types/network.interface'; +import { SushiswapBentoboxVaultContractPositionFetcher } from '../common/sushiswap-bentobox.vault.contract-position-fetcher'; -import { SushiSwapBentoBoxContractPositionHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const appId = SUSHISWAP_BENTOBOX_DEFINITION.id; -const groupId = SUSHISWAP_BENTOBOX_DEFINITION.groups.vault.id; -const network = Network.ETHEREUM_MAINNET; - -@Register.ContractPositionFetcher({ appId, groupId, network }) -export class EthereumSushiSwapBentoBoxContractPositionFetcher implements PositionFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionHelper) - private readonly positionHelper: SushiSwapBentoBoxContractPositionHelper, - ) {} - - async getPositions() { - return this.positionHelper.getPositions({ - bentoBoxAddress: '0xf5bce5077908a1b7370b9ae04adc565ebd643966', - network, - subgraphUrl: 'https://api.thegraph.com/subgraphs/name/sushiswap/bentobox', - dependencies: [{ appId: 'sushiswap', groupIds: ['x-sushi', 'meowshi'], network }], - }); - } +@PositionTemplate() +export class EthereumSushiSwapBentoBoxContractPositionFetcher extends SushiswapBentoboxVaultContractPositionFetcher { + groupLabel = 'BentoBox'; + subgraphUrl = 'https://api.thegraph.com/subgraphs/name/sushiswap/bentobox'; + bentoboxAddress = '0xf5bce5077908a1b7370b9ae04adc565ebd643966'; } diff --git a/src/apps/sushiswap-bentobox/fantom/sushiswap-bentobox.vault.contract-position-fetcher.ts b/src/apps/sushiswap-bentobox/fantom/sushiswap-bentobox.vault.contract-position-fetcher.ts new file mode 100644 index 000000000..dd64990ca --- /dev/null +++ b/src/apps/sushiswap-bentobox/fantom/sushiswap-bentobox.vault.contract-position-fetcher.ts @@ -0,0 +1,10 @@ +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; + +import { SushiswapBentoboxVaultContractPositionFetcher } from '../common/sushiswap-bentobox.vault.contract-position-fetcher'; + +@PositionTemplate() +export class FantomSushiSwapBentoBoxContractPositionFetcher extends SushiswapBentoboxVaultContractPositionFetcher { + groupLabel = 'BentoBox'; + subgraphUrl = 'https://api.thegraph.com/subgraphs/name/sushiswap/bentobox-fantom'; + bentoboxAddress = '0xf5bce5077908a1b7370b9ae04adc565ebd643966'; +} diff --git a/src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-balance-helper.ts b/src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-balance-helper.ts deleted file mode 100644 index fe2d657b6..000000000 --- a/src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-balance-helper.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; - -import { ContractPositionBalanceHelper } from '~app-toolkit/helpers/balance/contract-position-balance.helper'; -import { drillBalance } from '~app-toolkit/helpers/balance/token-balance.helper'; -import { Network } from '~types/network.interface'; - -import { SushiswapBentoboxContractFactory } from '../contracts'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -@Injectable() -export class SushiSwapBentoBoxContractPositionBalanceHelper { - constructor( - @Inject(SushiswapBentoboxContractFactory) private readonly contractFactory: SushiswapBentoboxContractFactory, - @Inject(ContractPositionBalanceHelper) - private readonly contractPositionBalanceHelper: ContractPositionBalanceHelper, - ) {} - - getBalances({ address, bentoBoxAddress, network }: { address: string; network: Network; bentoBoxAddress: string }) { - return this.contractPositionBalanceHelper.getContractPositionBalances({ - network, - appId: SUSHISWAP_BENTOBOX_DEFINITION.id, - groupId: SUSHISWAP_BENTOBOX_DEFINITION.groups.vault.id, - address, - resolveBalances: async ({ address, multicall, contractPosition }) => { - const contract = this.contractFactory.sushiswapBentobox({ address: bentoBoxAddress, network }); - const [token] = contractPosition.tokens; - const balance = await multicall.wrap(contract).balanceOf(token.address, address); - return [drillBalance(token, balance.toString())]; - }, - }); - } -} diff --git a/src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-helper.ts b/src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-helper.ts deleted file mode 100644 index a222fdbf9..000000000 --- a/src/apps/sushiswap-bentobox/helpers/sushiswap-bentobox.vault.contract-position-helper.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { Inject, Injectable } from '@nestjs/common'; -import request, { gql } from 'graphql-request'; -import _ from 'lodash'; -import moment from 'moment'; - -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 { Cache } from '~cache/cache.decorator'; -import { ContractType } from '~position/contract.interface'; -import { ContractPosition } from '~position/position.interface'; -import { AppGroupsDefinition } from '~position/position.service'; -import { supplied } from '~position/position.utils'; -import { Network } from '~types/network.interface'; - -import { SushiswapBentoboxContractFactory } from '../contracts'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -type TokensResponse = { - tokens?: { - id: string; - }[]; -}; - -const allTokensQuery = gql` - { - tokens(first: 500) { - id - } - } -`; - -type SushiswapBentoBoxGetPositionParams = { - bentoBoxAddress: string; - network: Network; - subgraphUrl: string; - dependencies?: AppGroupsDefinition[]; -}; - -const appId = SUSHISWAP_BENTOBOX_DEFINITION.id; -const groupId = SUSHISWAP_BENTOBOX_DEFINITION.groups.vault.id; - -@Injectable() -export class SushiSwapBentoBoxContractPositionHelper { - constructor( - @Inject(SushiswapBentoboxContractFactory) - private readonly sushiSwapBentoBoxContractFactory: SushiswapBentoboxContractFactory, - @Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit, - ) {} - - @Cache({ - instance: 'business', - key: ({ network }: { url: string; network: Network }) => - `apps-v3:${SUSHISWAP_BENTOBOX_DEFINITION.id}:${network}:api-data`, - ttl: moment.duration(1, 'hour').asSeconds(), - }) - private async getBentoBoxTokens(opts: { url: string; network: Network }) { - const response = await request(opts.url, allTokensQuery, {}); - return response.tokens ?? []; - } - - async getPositions({ bentoBoxAddress, network, subgraphUrl, dependencies = [] }: SushiswapBentoBoxGetPositionParams) { - const multicall = this.appToolkit.getMulticall(network); - const baseTokens = await this.appToolkit.getBaseTokenPrices(network); - const appTokens = await this.appToolkit.getAppTokenPositions(...dependencies); - const allTokens = [...appTokens, ...baseTokens]; - - // Get all configured tokens in this Bentobox - const bentoBoxTokens = await this.getBentoBoxTokens({ url: subgraphUrl, network }); - - const positions = await Promise.all( - bentoBoxTokens.map(async token => { - const tokenAddress = token.id.toLowerCase(); - - const underlyingToken = allTokens.find(p => p.address === tokenAddress); - if (!underlyingToken) return null; - - const tokenContract = this.sushiSwapBentoBoxContractFactory.erc20({ address: tokenAddress, network }); - const balanceOfRaw = await multicall.wrap(tokenContract).balanceOf(bentoBoxAddress); - const balanceOf = Number(balanceOfRaw) / 10 ** underlyingToken.decimals; - const liquidity = balanceOf * underlyingToken.price; - - const position: ContractPosition = { - type: ContractType.POSITION, - address: bentoBoxAddress, - network, - appId, - groupId, - tokens: [supplied(underlyingToken)], - dataProps: { - liquidity, - }, - displayProps: { - statsItems: [{ label: 'Liquidity', value: buildDollarDisplayItem(liquidity) }], - label: `${underlyingToken.symbol} Deposit`, - secondaryLabel: buildDollarDisplayItem(underlyingToken.price), - images: [getTokenImg(underlyingToken.address, network)], - }, - }; - - return position; - }), - ); - - return _.compact(positions); - } -} diff --git a/src/apps/sushiswap-bentobox/index.ts b/src/apps/sushiswap-bentobox/index.ts index a98dfa90a..97ca5c6df 100644 --- a/src/apps/sushiswap-bentobox/index.ts +++ b/src/apps/sushiswap-bentobox/index.ts @@ -1,6 +1,3 @@ export { SushiSwapBentoBoxAppDefinition, SUSHISWAP_BENTOBOX_DEFINITION } from './sushiswap-bentobox.definition'; export { SushiSwapBentoBoxAppModule } from './sushiswap-bentobox.module'; export { SushiswapBentoboxContractFactory } from './contracts'; - -export { SushiSwapBentoBoxContractPositionBalanceHelper } from './helpers/sushiswap-bentobox.vault.contract-position-balance-helper'; -export { SushiSwapBentoBoxContractPositionHelper } from './helpers/sushiswap-bentobox.vault.contract-position-helper'; diff --git a/src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.balance-fetcher.ts b/src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.balance-fetcher.ts deleted file mode 100644 index 2b7751647..000000000 --- a/src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.balance-fetcher.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Inject } from '@nestjs/common'; - -import { Register } from '~app-toolkit/decorators'; -import { presentBalanceFetcherResponse } from '~app-toolkit/helpers/presentation/balance-fetcher-response.present'; -import { BalanceFetcher } from '~balance/balance-fetcher.interface'; -import { Network } from '~types/network.interface'; - -import { SushiSwapBentoBoxContractPositionBalanceHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-balance-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const network = Network.POLYGON_MAINNET; - -@Register.BalanceFetcher(SUSHISWAP_BENTOBOX_DEFINITION.id, network) -export class PolygonSushiSwapBentoBoxBalanceFetcher implements BalanceFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionBalanceHelper) - private readonly balanceHelper: SushiSwapBentoBoxContractPositionBalanceHelper, - ) {} - - async getBalances(address: string) { - const balances = await this.balanceHelper.getBalances({ - address, - network, - bentoBoxAddress: '0x0319000133d3ada02600f0875d2cf03d442c3367', - }); - - return presentBalanceFetcherResponse([ - { - label: 'SushiSwap BentoBox', - assets: balances, - }, - ]); - } -} diff --git a/src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.vault.contract-position-fetcher.ts b/src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.vault.contract-position-fetcher.ts index 30a4b1d85..12b2eb482 100644 --- a/src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.vault.contract-position-fetcher.ts +++ b/src/apps/sushiswap-bentobox/polygon/sushiswap-bentobox.vault.contract-position-fetcher.ts @@ -1,30 +1,10 @@ -import { Inject } from '@nestjs/common'; +import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator'; -import { Register } from '~app-toolkit/decorators'; -import { PositionFetcher } from '~position/position-fetcher.interface'; -import { ContractPosition } from '~position/position.interface'; -import { Network } from '~types/network.interface'; +import { SushiswapBentoboxVaultContractPositionFetcher } from '../common/sushiswap-bentobox.vault.contract-position-fetcher'; -import { SushiSwapBentoBoxContractPositionHelper } from '../helpers/sushiswap-bentobox.vault.contract-position-helper'; -import { SUSHISWAP_BENTOBOX_DEFINITION } from '../sushiswap-bentobox.definition'; - -const appId = SUSHISWAP_BENTOBOX_DEFINITION.id; -const groupId = SUSHISWAP_BENTOBOX_DEFINITION.groups.vault.id; -const network = Network.POLYGON_MAINNET; - -@Register.ContractPositionFetcher({ appId, groupId, network }) -export class PolygonSushiSwapBentoBoxContractPositionFetcher implements PositionFetcher { - constructor( - @Inject(SushiSwapBentoBoxContractPositionHelper) - private readonly positionHelper: SushiSwapBentoBoxContractPositionHelper, - ) {} - - async getPositions() { - return this.positionHelper.getPositions({ - bentoBoxAddress: '0x0319000133d3ada02600f0875d2cf03d442c3367', - network, - subgraphUrl: 'https://api.thegraph.com/subgraphs/name/matthewlilley/bentobox-polygon', - //subgraphUrl: 'https://api.thegraph.com/subgraphs/name/sushiswap/matic-bentobox', - currently failling to sync - }); - } +@PositionTemplate() +export class PolygonSushiSwapBentoBoxContractPositionFetcher extends SushiswapBentoboxVaultContractPositionFetcher { + groupLabel = 'BentoBox'; + subgraphUrl = 'https://api.thegraph.com/subgraphs/name/matthewlilley/bentobox-polygon'; + bentoboxAddress = '0x0319000133d3ada02600f0875d2cf03d442c3367'; } diff --git a/src/apps/sushiswap-bentobox/sushiswap-bentobox.definition.ts b/src/apps/sushiswap-bentobox/sushiswap-bentobox.definition.ts index 1325a6680..640d26298 100644 --- a/src/apps/sushiswap-bentobox/sushiswap-bentobox.definition.ts +++ b/src/apps/sushiswap-bentobox/sushiswap-bentobox.definition.ts @@ -20,8 +20,10 @@ export const SUSHISWAP_BENTOBOX_DEFINITION = appDefinition({ }, supportedNetworks: { [Network.ARBITRUM_MAINNET]: [AppAction.VIEW], + [Network.AVALANCHE_MAINNET]: [AppAction.VIEW], [Network.BINANCE_SMART_CHAIN_MAINNET]: [AppAction.VIEW], [Network.ETHEREUM_MAINNET]: [AppAction.VIEW], + [Network.FANTOM_OPERA_MAINNET]: [AppAction.VIEW], [Network.POLYGON_MAINNET]: [AppAction.VIEW], }, primaryColor: '#887eb3', diff --git a/src/apps/sushiswap-bentobox/sushiswap-bentobox.module.ts b/src/apps/sushiswap-bentobox/sushiswap-bentobox.module.ts index 2ac00df16..892dd1752 100644 --- a/src/apps/sushiswap-bentobox/sushiswap-bentobox.module.ts +++ b/src/apps/sushiswap-bentobox/sushiswap-bentobox.module.ts @@ -1,16 +1,13 @@ import { Register } from '~app-toolkit/decorators'; import { AbstractApp } from '~app/app.dynamic-module'; -import { ArbitrumSushiSwapBentoBoxBalanceFetcher } from './arbitrum/sushiswap-bentobox.balance-fetcher'; import { ArbitrumSushiSwapBentoBoxContractPositionFetcher } from './arbitrum/sushiswap-bentobox.vault.contract-position-fetcher'; -import { BscSushiSwapBentoBoxBalanceFetcher } from './binance-smart-chain/sushiswap-bentobox.balance-fetcher'; -import { BscSushiSwapBentoBoxContractPositionFetcher } from './binance-smart-chain/sushiswap-bentobox.vault.contract-position-fetcher'; +import { AvalancheSushiSwapBentoBoxContractPositionFetcher } from './avalanche/sushiswap-bentobox.vault.contract-position-fetcher'; +import { BinanceSmartChainSushiSwapBentoBoxContractPositionFetcher } from './binance-smart-chain/sushiswap-bentobox.vault.contract-position-fetcher'; +import { SushiswapBentoboxVaultTokensResolver } from './common/sushiswap-bentobox.vault-tokens-resolver'; import { SushiswapBentoboxContractFactory } from './contracts'; -import { EthereumSushiSwapBentoBoxBalanceFetcher } from './ethereum/sushiswap-bentobox.balance-fetcher'; import { EthereumSushiSwapBentoBoxContractPositionFetcher } from './ethereum/sushiswap-bentobox.vault.contract-position-fetcher'; -import { SushiSwapBentoBoxContractPositionBalanceHelper } from './helpers/sushiswap-bentobox.vault.contract-position-balance-helper'; -import { SushiSwapBentoBoxContractPositionHelper } from './helpers/sushiswap-bentobox.vault.contract-position-helper'; -import { PolygonSushiSwapBentoBoxBalanceFetcher } from './polygon/sushiswap-bentobox.balance-fetcher'; +import { FantomSushiSwapBentoBoxContractPositionFetcher } from './fantom/sushiswap-bentobox.vault.contract-position-fetcher'; import { PolygonSushiSwapBentoBoxContractPositionFetcher } from './polygon/sushiswap-bentobox.vault.contract-position-fetcher'; import { SushiSwapBentoBoxAppDefinition, SUSHISWAP_BENTOBOX_DEFINITION } from './sushiswap-bentobox.definition'; @@ -19,27 +16,19 @@ import { SushiSwapBentoBoxAppDefinition, SUSHISWAP_BENTOBOX_DEFINITION } from '. providers: [ SushiSwapBentoBoxAppDefinition, SushiswapBentoboxContractFactory, - SushiSwapBentoBoxContractPositionBalanceHelper, - SushiSwapBentoBoxContractPositionHelper, + SushiswapBentoboxVaultTokensResolver, // Arbitrum ArbitrumSushiSwapBentoBoxContractPositionFetcher, - ArbitrumSushiSwapBentoBoxBalanceFetcher, + // Avalanche + AvalancheSushiSwapBentoBoxContractPositionFetcher, // Binance Smart Chain - BscSushiSwapBentoBoxContractPositionFetcher, - BscSushiSwapBentoBoxBalanceFetcher, + BinanceSmartChainSushiSwapBentoBoxContractPositionFetcher, // Ethereum EthereumSushiSwapBentoBoxContractPositionFetcher, - EthereumSushiSwapBentoBoxBalanceFetcher, + // Fantom + FantomSushiSwapBentoBoxContractPositionFetcher, // Polygon PolygonSushiSwapBentoBoxContractPositionFetcher, - PolygonSushiSwapBentoBoxBalanceFetcher, - ], - exports: [ - SushiSwapBentoBoxAppDefinition, - SushiSwapBentoBoxAppModule, - SushiswapBentoboxContractFactory, - SushiSwapBentoBoxContractPositionBalanceHelper, - SushiSwapBentoBoxContractPositionHelper, ], }) export class SushiSwapBentoBoxAppModule extends AbstractApp() {}