Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Commit

Permalink
fix: Split Olympus bond balance helper for v1 and v2 bonds, keep bond…
Browse files Browse the repository at this point in the history
… position fetcher generic, fix lint error (#242)
  • Loading branch information
immasandwich authored Apr 23, 2022
1 parent cbde9d4 commit 0ea4021
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 44 deletions.
24 changes: 6 additions & 18 deletions src/apps/olympus/ethereum/olympus.balance-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import { BalanceFetcher } from '~balance/balance-fetcher.interface';
import { APP_TOOLKIT, IAppToolkit } from '~lib';
import { Network } from '~types/network.interface';

import { OlympusContractFactory, OlympusV2BondDepository } from '../contracts';
import { OlympusBondContractPositionBalanceHelper } from '../helpers/olympus.bond.contract-position-balance-helper';
import { OlympusContractFactory } from '../contracts';
import { OlympusBondV2ContractPositionBalanceHelper } from '../helpers/olympus.bond-v2.contract-position-balance-helper';
import { OLYMPUS_DEFINITION } from '../olympus.definition';

@Register.BalanceFetcher(OLYMPUS_DEFINITION.id, Network.ETHEREUM_MAINNET)
export class EthereumOlympusBalanceFetcher implements BalanceFetcher {
constructor(
@Inject(OlympusContractFactory) private readonly contractFactory: OlympusContractFactory,
@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit,
@Inject(OlympusBondContractPositionBalanceHelper)
private readonly contractPositionBalanceHelper: OlympusBondContractPositionBalanceHelper,
@Inject(OlympusBondV2ContractPositionBalanceHelper)
private readonly contractPositionBalanceHelper: OlympusBondV2ContractPositionBalanceHelper,
) {}

private async getTokenBalances(address: string) {
Expand Down Expand Up @@ -45,35 +45,23 @@ export class EthereumOlympusBalanceFetcher implements BalanceFetcher {

private async getBonds(address: string) {
const network = Network.ETHEREUM_MAINNET;
return this.contractPositionBalanceHelper.getBalances<OlympusV2BondDepository>({
return this.contractPositionBalanceHelper.getBalances({
network,
groupId: OLYMPUS_DEFINITION.groups.bond.id,
appId: OLYMPUS_DEFINITION.id,
address,
resolveDepositoryContract: ({ depositoryAddress: address }) => {
return this.contractFactory.olympusV2BondDepository({ address, network });
},
resolveClaimablePayout: ({ multicall, contract, address }) =>
multicall
.wrap(contract)
.indexesFor(address)
.then(
async indexes =>
await Promise.all(indexes.map(index => multicall.wrap(contract).pendingFor(address, index))),
),
});
}

async getBalances(address: string) {
const [stakedAssets, bonds] = await Promise.all([this.getTokenBalances(address), this.getBonds(address)]);

return presentBalanceFetcherResponse([
{
label: 'Staked',
assets: stakedAssets,
},
{
label: 'Bond',
label: 'Bonds',
assets: bonds,
},
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ export class EthereumOlympusBondContractPositionFetcher implements PositionFetch
return this.olympusContractPositionHelper.getPositions({
appId: OLYMPUS_DEFINITION.id,
network,
mintedTokenAddress: '0x0ab87046fbb341d058f17cbc4c1133f25a20a52f', // gOHM
groupId: OLYMPUS_DEFINITION.groups.bond.id,
depositories,
dependencies: [{ appId: OLYMPUS_DEFINITION.id, groupIds: [OLYMPUS_DEFINITION.groups.gOhm.id], network }],
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Inject, Injectable } from '@nestjs/common';
import { BigNumber } from 'ethers';
import BigNumber from 'bignumber.js';
import { BigNumberish } from 'ethers';
import { sumBy } from 'lodash';

import { drillBalance } from '~app-toolkit';
Expand All @@ -11,49 +12,59 @@ import { ContractPosition } from '~position/position.interface';
import { isClaimable, isVesting } from '~position/position.utils';
import { Network } from '~types/network.interface';

type OlympusBondContractPositionBalanceHelperParams<T, V> = {
type OlympusBondV1ContractPositionBalanceHelperParams<T, V> = {
address: string;
appId: string;
groupId: string;
network: Network;
resolveDepositoryContract: (opts: { depositoryAddress: string; network: Network }) => T;
resolveTotalPayout: (opts: {
multicall: Multicall;
contract: T;
address: string;
contractPosition: ContractPosition<V>;
}) => Promise<BigNumberish>;
resolveClaimablePayout: (opts: {
multicall: Multicall;
contract: T;
address: string;
contractPosition: ContractPosition<V>;
}) => Promise<any>;
}) => Promise<BigNumberish>;
};

@Injectable()
export class OlympusBondContractPositionBalanceHelper {
export class OlympusBondV1ContractPositionBalanceHelper {
constructor(@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit) {}

async getBalances<T, V = DefaultDataProps>(
opts: OlympusBondContractPositionBalanceHelperParams<T, V>,
opts: OlympusBondV1ContractPositionBalanceHelperParams<T, V>,
): Promise<ContractPositionBalance<V>[]> {
const { address, appId, groupId, network, resolveDepositoryContract, resolveClaimablePayout } = opts;
const { address, appId, groupId, network, resolveDepositoryContract, resolveTotalPayout, resolveClaimablePayout } =
opts;

const multicall = this.appToolkit.getMulticall(network);
const contractPositions = await this.appToolkit.getAppContractPositions<V>({ network, appId, groupIds: [groupId] });

const contractPositionBalances = await Promise.all(
contractPositions.map(async contractPosition => {
const contract = resolveDepositoryContract({ depositoryAddress: contractPosition.address, network });

const vestingToken = contractPosition.tokens.find(isVesting)!;
const claimableToken = contractPosition.tokens.find(isClaimable)!;

const [claimableBalanceRaw] = await Promise.all([
const [pendingPayoutRaw, claimableBalanceRaw] = await Promise.all([
resolveTotalPayout({ multicall, contract, address, contractPosition }),
resolveClaimablePayout({ multicall, contract, address, contractPosition }),
]);

const claimableBonds = claimableBalanceRaw.filter(p => p.matured_);
const vestingBonds = claimableBalanceRaw.filter(p => !p.matured_);
const pendingPayoutRawBN = new BigNumber(pendingPayoutRaw.toString());
const claimableBalanceRawBN = new BigNumber(claimableBalanceRaw.toString());

const claimableAmount = claimableBonds.reduce((acc, bond) => acc.add(bond.payout_), BigNumber.from('0'));
const vestingAmount = vestingBonds.reduce((acc, bond) => {
return acc.add(bond.payout_);
}, BigNumber.from('0'));
const claimableTokenBalance = drillBalance(claimableToken, claimableAmount.toString());
const vestingTokenBalance = drillBalance(vestingToken, vestingAmount.toString());
const vestingBalanceRaw = pendingPayoutRawBN.gt(claimableBalanceRawBN)
? pendingPayoutRawBN.minus(claimableBalanceRawBN).toFixed(0)
: '0';
const claimableTokenBalance = drillBalance(claimableToken, claimableBalanceRaw.toString());
const vestingTokenBalance = drillBalance(vestingToken, vestingBalanceRaw);
const tokens = [claimableTokenBalance, vestingTokenBalance].filter(v => v.balanceUSD > 0);
const balanceUSD = sumBy(tokens, t => t.balanceUSD);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { Inject, Injectable } from '@nestjs/common';
import { BigNumber } from 'ethers';
import { sumBy } from 'lodash';

import { drillBalance } from '~app-toolkit';
import { APP_TOOLKIT, IAppToolkit } from '~lib';
import { ContractPositionBalance } from '~position/position-balance.interface';
import { isClaimable, isVesting } from '~position/position.utils';
import { Network } from '~types/network.interface';

import { OlympusContractFactory } from '../contracts';

type OlympusBondV2ContractPositionBalanceHelperParams = {
address: string;
appId: string;
groupId: string;
network: Network;
};

@Injectable()
export class OlympusBondV2ContractPositionBalanceHelper {
constructor(
@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit,
@Inject(OlympusContractFactory) private readonly contractFactory: OlympusContractFactory,
) {}

async getBalances(opts: OlympusBondV2ContractPositionBalanceHelperParams): Promise<ContractPositionBalance[]> {
const { address, appId, groupId, network } = opts;
const multicall = this.appToolkit.getMulticall(network);
const contractPositions = await this.appToolkit.getAppContractPositions({ network, appId, groupIds: [groupId] });
const contractPositionBalances = await Promise.all(
contractPositions.map(async contractPosition => {
const contract = this.contractFactory.olympusV2BondDepository({ address: contractPosition.address, network });
const vestingToken = contractPosition.tokens.find(isVesting)!;
const claimableToken = contractPosition.tokens.find(isClaimable)!;

const indexes = await multicall.wrap(contract).indexesFor(address);
const pendingBonds = await Promise.all(
indexes.map(index => multicall.wrap(contract).pendingFor(address, index)),
);

const claimableBonds = pendingBonds.filter(p => p.matured_);
const vestingBonds = pendingBonds.filter(p => !p.matured_);

const claimableAmount = claimableBonds.reduce((acc, bond) => acc.add(bond.payout_), BigNumber.from('0'));
const vestingAmount = vestingBonds.reduce((acc, bond) => {
return acc.add(bond.payout_);
}, BigNumber.from('0'));
const claimableTokenBalance = drillBalance(claimableToken, claimableAmount.toString());
const vestingTokenBalance = drillBalance(vestingToken, vestingAmount.toString());
const tokens = [claimableTokenBalance, vestingTokenBalance].filter(v => v.balanceUSD > 0);
const balanceUSD = sumBy(tokens, t => t.balanceUSD);

return { ...contractPosition, tokens, balanceUSD };
}),
);

return contractPositionBalances;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import { AppGroupsDefinition } from '~position/position.service';
import { claimable, vesting } from '~position/position.utils';
import { Network } from '~types/network.interface';

import { OLYMPUS_DEFINITION } from '../olympus.definition';

type OlympusDepository = {
depositoryAddress: string;
symbol: string;
Expand All @@ -21,6 +19,7 @@ type OlympusBondContractPositionHelperParams = {
appId: string;
groupId: string;
network: Network;
mintedTokenAddress: string;
depositories: OlympusDepository[];
dependencies?: AppGroupsDefinition[];
};
Expand All @@ -34,18 +33,18 @@ export class OlympusBondContractPositionHelper {
groupId,
network,
depositories,

dependencies = [{ appId, groupIds: [OLYMPUS_DEFINITION.groups.gOhm.id], network }],
mintedTokenAddress,
dependencies = [],
}: OlympusBondContractPositionHelperParams) {
const [baseTokens, appTokens] = await Promise.all([
this.appToolkit.getBaseTokenPrices(network),
this.appToolkit.getAppTokenPositions(...dependencies),
]);
const allTokens = [...appTokens, ...baseTokens];

const mintedToken = allTokens.find(token => token.symbol === 'gOHM');
const mintedToken = allTokens.find(token => token.address === mintedTokenAddress);
if (!mintedToken) {
throw new Error(`minted token with address gOHM is missing`);
throw new Error(`minted token with address ${mintedTokenAddress} is missing`);
}

const depositoryContractPositions = await Promise.all(
Expand All @@ -59,7 +58,7 @@ export class OlympusBondContractPositionHelper {
tokens: [vesting(mintedToken), claimable(mintedToken)],
dataProps: {},
displayProps: {
label: `Bond`,
label: `${symbol} Bond`,
images: images || [getTokenImg(symbol, network)],
statsItems: [],
},
Expand Down
9 changes: 6 additions & 3 deletions src/apps/olympus/olympus.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ import { EthereumOlympusSOhmTokenFetcher } from './ethereum/olympus.s-ohm.token-
import { EthereumOlympusWsOhmV1TokenFetcher } from './ethereum/olympus.ws-ohm-v1.token-fetcher';
import { FantomOlympusBalanceFetcher } from './fantom/olympus.balance-fetcher';
import { FantomOlympusGOhmTokenFetcher } from './fantom/olympus.g-ohm.token-fetcher';
import { OlympusBondContractPositionBalanceHelper } from './helpers/olympus.bond.contract-position-balance-helper';
import { OlympusBondV1ContractPositionBalanceHelper } from './helpers/olympus.bond-v1.contract-position-balance-helper';
import { OlympusBondV2ContractPositionBalanceHelper } from './helpers/olympus.bond-v2.contract-position-balance-helper';
import { OlympusBondContractPositionHelper } from './helpers/olympus.bond.contract-position-helper';
import { OlympusBridgeTokenHelper } from './helpers/olympus.bridge-token-helper';
import { OlympusAppDefinition } from './olympus.definition';
Expand Down Expand Up @@ -52,13 +53,15 @@ import { PolygonOlympusGOhmTokenFetcher } from './polygon/olympus.g-ohm.token-fe
// Helpers
OlympusBridgeTokenHelper,
OlympusBondContractPositionHelper,
OlympusBondContractPositionBalanceHelper,
OlympusBondV1ContractPositionBalanceHelper,
OlympusBondV2ContractPositionBalanceHelper,
],
exports: [
OlympusAppDefinition,
OlympusContractFactory,
OlympusBondContractPositionHelper,
OlympusBondContractPositionBalanceHelper,
OlympusBondV1ContractPositionBalanceHelper,
OlympusBondV2ContractPositionBalanceHelper,
OlympusBridgeTokenHelper,
],
})
Expand Down
2 changes: 1 addition & 1 deletion src/apps/tokemak/ethereum/tokemak.balance-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class EthereumTokemakBalanceFetcher implements BalanceFetcher {
}

async getClaimableBalanceData(address: string) {
const [latestClaimableRewardsHash, _] = await this.getCycleRewardsHash();
const [latestClaimableRewardsHash] = await this.getCycleRewardsHash();
const url = `https://ipfs.tokemaklabs.xyz/ipfs/${latestClaimableRewardsHash}/${address.toLowerCase()}.json`;
const data: ClaimableDataResponse['payload'] | null = await Axios.get<ClaimableDataResponse>(url)
.then(t => t.data.payload)
Expand Down

0 comments on commit 0ea4021

Please sign in to comment.