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

Commit

Permalink
feat(curve): Add child liquidity gauges to Optimism (#451)
Browse files Browse the repository at this point in the history
  • Loading branch information
immasandwich committed May 17, 2022
1 parent aa4054c commit a9c218e
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 91 deletions.
Expand Up @@ -38,7 +38,7 @@ export class ArbitrumCurveFarmContractPositionFetcher implements PositionFetcher
private readonly childGaugeRewardTokenStrategy: CurveChildLiquidityGaugeRewardTokenStrategy,
) {}

async getRewardOnlyGaugePositions() {
async getRewardsOnlyGaugePositions() {
const definitions = [CURVE_V1_POOL_DEFINITIONS, CURVE_V2_POOL_DEFINITIONS].flat().filter(v => !!v.gaugeAddress);

return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<CurveRewardsOnlyGauge>({
Expand Down Expand Up @@ -85,7 +85,7 @@ export class ArbitrumCurveFarmContractPositionFetcher implements PositionFetcher

async getPositions() {
const [rewardOnlyGaugePositions, childLiquidityGaugePositions] = await Promise.all([
this.getRewardOnlyGaugePositions(),
this.getRewardsOnlyGaugePositions(),
this.getChildLiquidityGaugePositions(),
]);

Expand Down
Expand Up @@ -38,7 +38,7 @@ export class AvalancheCurveFarmContractPositionFetcher implements PositionFetche
private readonly childGaugeRewardTokenStrategy: CurveChildLiquidityGaugeRewardTokenStrategy,
) {}

async getRewardOnlyGaugePositions() {
async getRewardsOnlyGaugePositions() {
const definitions = [CURVE_V1_POOL_DEFINITIONS, CURVE_V2_POOL_DEFINITIONS].flat().filter(v => !!v.gaugeAddress);

return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<CurveRewardsOnlyGauge>({
Expand Down Expand Up @@ -84,7 +84,7 @@ export class AvalancheCurveFarmContractPositionFetcher implements PositionFetche

async getPositions() {
const [rewardOnlyGaugePositions, childLiquidityGaugePositions] = await Promise.all([
this.getRewardOnlyGaugePositions(),
this.getRewardsOnlyGaugePositions(),
this.getChildLiquidityGaugePositions(),
]);

Expand Down
4 changes: 2 additions & 2 deletions src/apps/curve/fantom/curve.farm.contract-position-fetcher.ts
Expand Up @@ -42,7 +42,7 @@ export class FantomCurveFarmContractPositionFetcher implements PositionFetcher<C
private readonly childGaugeRewardTokenStrategy: CurveChildLiquidityGaugeRewardTokenStrategy,
) {}

async getRewardOnlyGaugePositions() {
async getRewardsOnlyGaugePositions() {
const definitions = [CURVE_V1_POOL_DEFINITIONS, CURVE_V1_METAPOOL_DEFINITIONS, CURVE_V2_POOL_DEFINITIONS]
.flat()
.filter(v => !!v.gaugeAddress);
Expand Down Expand Up @@ -90,7 +90,7 @@ export class FantomCurveFarmContractPositionFetcher implements PositionFetcher<C

async getPositions() {
const [rewardOnlyGaugePositions, childLiquidityGaugePositions] = await Promise.all([
this.getRewardOnlyGaugePositions(),
this.getRewardsOnlyGaugePositions(),
this.getChildLiquidityGaugePositions(),
]);

Expand Down
6 changes: 3 additions & 3 deletions src/apps/curve/gnosis/curve.farm.contract-position-fetcher.ts
Expand Up @@ -38,8 +38,8 @@ export class GnosisCurveFarmContractPositionFetcher implements PositionFetcher<C
private readonly childGaugeRewardTokenStrategy: CurveChildLiquidityGaugeRewardTokenStrategy,
) {}

async getRewardOnlyGaugePositions() {
const definitions = CURVE_V1_POOL_DEFINITIONS.filter(v => !!v.gaugeAddress);
async getRewardsOnlyGaugePositions() {
const definitions = [CURVE_V1_POOL_DEFINITIONS].flat().filter(v => !!v.gaugeAddress);

return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<CurveRewardsOnlyGauge>({
network,
Expand Down Expand Up @@ -84,7 +84,7 @@ export class GnosisCurveFarmContractPositionFetcher implements PositionFetcher<C

async getPositions() {
const [rewardOnlyGaugePositions, childLiquidityGaugePositions] = await Promise.all([
this.getRewardOnlyGaugePositions(),
this.getRewardsOnlyGaugePositions(),
this.getChildLiquidityGaugePositions(),
]);

Expand Down
83 changes: 40 additions & 43 deletions src/apps/curve/optimism/curve.balance-fetcher.ts
Expand Up @@ -7,7 +7,7 @@ import { BalanceFetcher } from '~balance/balance-fetcher.interface';
import { isClaimable } from '~position/position.utils';
import { Network } from '~types/network.interface';

import { CurveContractFactory, CurveNGauge, CurveRewardsOnlyGauge } from '../contracts';
import { CurveChildLiquidityGauge, CurveContractFactory, CurveRewardsOnlyGauge } from '../contracts';
import { CURVE_DEFINITION } from '../curve.definition';

@Register.BalanceFetcher(CURVE_DEFINITION.id, Network.OPTIMISM_MAINNET)
Expand All @@ -26,53 +26,50 @@ export class OptimismCurveBalanceFetcher implements BalanceFetcher {
});
}

private async getStakedBalances(address: string) {
return Promise.all([
// Single Gauge
this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances<CurveRewardsOnlyGauge>({
address,
appId: CURVE_DEFINITION.id,
groupId: CURVE_DEFINITION.groups.farm.id,
network: Network.OPTIMISM_MAINNET,
resolveContract: ({ address, network }) =>
this.curveContractFactory.curveRewardsOnlyGauge({ address, network }),
resolveStakedTokenBalance: ({ contract, address, multicall }) => multicall.wrap(contract).balanceOf(address),
resolveRewardTokenBalances: ({ contract, address, multicall, contractPosition }) => {
const rewardTokens = contractPosition.tokens.filter(isClaimable);
const wrappedContract = multicall.wrap(contract);
return Promise.all(rewardTokens.map(v => wrappedContract.claimable_reward_write(address, v.address)));
},
}),
// N-Gauge
this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances<CurveNGauge>({
address,
network: Network.OPTIMISM_MAINNET,
appId: CURVE_DEFINITION.id,
groupId: CURVE_DEFINITION.groups.farm.id,
farmFilter: farm => farm.dataProps.implementation === 'n-gauge',
resolveContract: ({ address, network }) => this.curveContractFactory.curveNGauge({ address, network }),
resolveStakedTokenBalance: ({ contract, address, multicall }) => multicall.wrap(contract).balanceOf(address),
resolveRewardTokenBalances: async ({ contract, address, multicall, contractPosition }) => {
const rewardTokens = contractPosition.tokens.filter(isClaimable);
const wrappedContract = multicall.wrap(contract);
const primaryRewardBalance = await wrappedContract.claimable_tokens(address);
const rewardBalances = [primaryRewardBalance];
private async getRewardsOnlyGaugeStakedBalances(address: string) {
return this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances<CurveRewardsOnlyGauge>({
address,
appId: CURVE_DEFINITION.id,
groupId: CURVE_DEFINITION.groups.farm.id,
network: Network.OPTIMISM_MAINNET,
farmFilter: v => v.dataProps.implementation === 'rewards-only-gauge',
resolveContract: ({ address, network }) => this.curveContractFactory.curveRewardsOnlyGauge({ address, network }),
resolveStakedTokenBalance: ({ contract, address, multicall }) => multicall.wrap(contract).balanceOf(address),
resolveRewardTokenBalances: ({ contract, address, multicall, contractPosition }) => {
const rewardTokens = contractPosition.tokens.filter(isClaimable);
const wrappedContract = multicall.wrap(contract);
return Promise.all(rewardTokens.map(v => wrappedContract.claimable_reward_write(address, v.address)));
},
});
}

if (rewardTokens.length > 1) {
const secondaryRewardBalance = await wrappedContract.claimable_reward(address, rewardTokens[1].address);
rewardBalances.push(secondaryRewardBalance);
}
private async getChildLiquidityGaugeStakedBalances(address: string) {
return this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances<CurveChildLiquidityGauge>({
address,
appId: CURVE_DEFINITION.id,
groupId: CURVE_DEFINITION.groups.farm.id,
network: Network.OPTIMISM_MAINNET,
farmFilter: v => v.dataProps.implementation === 'child-liquidity-gauge',
resolveContract: ({ address, network }) =>
this.curveContractFactory.curveChildLiquidityGauge({ address, network }),
resolveStakedTokenBalance: ({ contract, address, multicall }) => multicall.wrap(contract).balanceOf(address),
resolveRewardTokenBalances: async ({ contract, address, multicall, contractPosition }) => {
const rewardTokens = contractPosition.tokens.filter(isClaimable);
const otherRewardTokens = rewardTokens.filter(v => v.symbol !== 'CRV');

return rewardBalances;
},
}),
]).then(v => v.flat());
return Promise.all([
multicall.wrap(contract).callStatic.claimable_tokens(address),
...otherRewardTokens.map(v => multicall.wrap(contract).claimable_reward(address, v.address)),
]);
},
});
}

async getBalances(address: string) {
const [poolTokenBalances, stakedBalances] = await Promise.all([
const [poolTokenBalances, rewardOnlyGaugeStakedBalances, childLiquidityGaugeStakedBalances] = await Promise.all([
this.getPoolTokenBalances(address),
this.getStakedBalances(address),
this.getRewardsOnlyGaugeStakedBalances(address),
this.getChildLiquidityGaugeStakedBalances(address),
]);

return presentBalanceFetcherResponse([
Expand All @@ -82,7 +79,7 @@ export class OptimismCurveBalanceFetcher implements BalanceFetcher {
},
{
label: 'Staked',
assets: stakedBalances,
assets: [...rewardOnlyGaugeStakedBalances, ...childLiquidityGaugeStakedBalances],
},
]);
}
Expand Down
81 changes: 44 additions & 37 deletions src/apps/curve/optimism/curve.farm.contract-position-fetcher.ts
@@ -1,18 +1,18 @@
import { Inject } from '@nestjs/common';

import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface';
import { ZERO_ADDRESS } from '~app-toolkit/constants/address';
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 { CurveContractFactory, CurveNGauge, CurveRewardsOnlyGauge } from '../contracts';
import { CurveChildLiquidityGauge, CurveContractFactory, CurveRewardsOnlyGauge } from '../contracts';
import { CURVE_DEFINITION } from '../curve.definition';
import { CurveFactoryGaugeAddressHelper } from '../helpers/curve.factory-gauge.address-helper';
import { CurveChildLiquidityGaugeFactoryAddressHelper } from '../helpers/curve.child-liquidity-gauge-factory.address-helper';
import { CurveChildLiquidityGaugeRewardTokenStrategy } from '../helpers/curve.child-liquidity-gauge.reward-token-strategy';
import { CurveChildLiquidityGaugeRoiStrategy } from '../helpers/curve.child-liquidity-gauge.roi-strategy';
import { CurveGaugeV2RewardTokenStrategy } from '../helpers/curve.gauge-v2.reward-token-strategy';
import { CurveGaugeV2RoiStrategy } from '../helpers/curve.gauge-v2.roi-strategy';
import { CurveGaugeIsActiveStrategy } from '../helpers/curve.gauge.is-active-strategy';

import { CURVE_V1_POOL_DEFINITIONS } from './curve.pool.definitions';

Expand All @@ -30,46 +30,23 @@ export class OptimismCurveFarmContractPositionFetcher implements PositionFetcher
private readonly curveGaugeV2RoiStrategy: CurveGaugeV2RoiStrategy,
@Inject(CurveGaugeV2RewardTokenStrategy)
private readonly curveGaugeV2RewardTokenStrategy: CurveGaugeV2RewardTokenStrategy,
@Inject(CurveFactoryGaugeAddressHelper)
private readonly curveFactoryGaugeAddressHelper: CurveFactoryGaugeAddressHelper,
@Inject(CurveGaugeIsActiveStrategy)
private readonly curveGaugeIsActiveStrategy: CurveGaugeIsActiveStrategy,
@Inject(CurveChildLiquidityGaugeFactoryAddressHelper)
private readonly childGaugeAddressHelper: CurveChildLiquidityGaugeFactoryAddressHelper,
@Inject(CurveChildLiquidityGaugeRoiStrategy)
private readonly childGaugeRoiStrategy: CurveChildLiquidityGaugeRoiStrategy,
@Inject(CurveChildLiquidityGaugeRewardTokenStrategy)
private readonly childGaugeRewardTokenStrategy: CurveChildLiquidityGaugeRewardTokenStrategy,
) {}

private async getNGaugeFarms() {
return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<CurveNGauge>({
network,
appId,
groupId,
dependencies: [{ appId: CURVE_DEFINITION.id, groupIds: [CURVE_DEFINITION.groups.pool.id], network }],
resolveFarmAddresses: async () => {
return await this.curveFactoryGaugeAddressHelper.getGaugeAddresses({
factoryAddress: '0x2db0e83599a91b508ac268a6197b8b14f5e72840',
network,
});
},
resolveImplementation: () => 'n-gauge',
resolveTotalValueLocked: ({ contract, multicall }) => multicall.wrap(contract).totalSupply(),
resolveFarmContract: ({ address, network }) => this.curveContractFactory.curveNGauge({ address, network }),
resolveStakedTokenAddress: ({ contract, multicall }) => multicall.wrap(contract).lp_token(),
resolveRewardTokenAddresses: async ({ contract, multicall }) => {
const bonusRewardTokenAddress = await multicall.wrap(contract).reward_tokens(0);
return [bonusRewardTokenAddress].filter(v => v !== ZERO_ADDRESS);
},
resolveIsActive: this.curveGaugeIsActiveStrategy.build({
resolveInflationRate: ({ contract, multicall }) => multicall.wrap(contract).inflation_rate(),
}),
resolveRois: async () => ({ dailyROI: 0, weeklyROI: 0, yearlyROI: 0 }),
});
}

async getSingleGaugeFarms() {
async getRewardsOnlyGaugePositions() {
const definitions = [CURVE_V1_POOL_DEFINITIONS].flat().filter(v => !!v.gaugeAddress);

return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<CurveRewardsOnlyGauge>({
network,
appId,
groupId,
dependencies: [{ appId: CURVE_DEFINITION.id, groupIds: [CURVE_DEFINITION.groups.pool.id], network }],
resolveImplementation: () => 'rewards-only-gauge',
resolveFarmAddresses: () => definitions.map(v => v.gaugeAddress ?? null),
resolveFarmContract: ({ address, network }) =>
this.curveContractFactory.curveRewardsOnlyGauge({ address, network }),
Expand All @@ -82,7 +59,37 @@ export class OptimismCurveFarmContractPositionFetcher implements PositionFetcher
});
}

async getChildLiquidityGaugePositions() {
return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<CurveChildLiquidityGauge>(
{
network,
appId,
groupId,
dependencies: [{ appId: CURVE_DEFINITION.id, groupIds: [CURVE_DEFINITION.groups.pool.id], network }],
resolveImplementation: () => 'child-liquidity-gauge',
resolveFarmAddresses: () =>
this.childGaugeAddressHelper.getGaugeAddresses({
factoryAddress: '0xabc000d88f23bb45525e447528dbf656a9d55bf5',
network,
}),
resolveFarmContract: ({ address, network }) =>
this.curveContractFactory.curveChildLiquidityGauge({ address, network }),
resolveStakedTokenAddress: ({ contract, multicall }) => multicall.wrap(contract).lp_token(),
resolveRewardTokenAddresses: this.childGaugeRewardTokenStrategy.build({
crvTokenAddress: '0x0994206dfe8de6ec6920ff4d779b0d950605fb53',
}),
resolveRois: this.childGaugeRoiStrategy.build(),
resolveIsActive: () => true,
},
);
}

async getPositions() {
return Promise.all([this.getSingleGaugeFarms(), this.getNGaugeFarms()]).then(v => v.flat());
const [rewardOnlyGaugePositions, childLiquidityGaugePositions] = await Promise.all([
this.getRewardsOnlyGaugePositions(),
this.getChildLiquidityGaugePositions(),
]);

return [...rewardOnlyGaugePositions, ...childLiquidityGaugePositions];
}
}
Expand Up @@ -38,7 +38,7 @@ export class PolygonCurveFarmContractPositionFetcher implements PositionFetcher<
private readonly childGaugeRewardTokenStrategy: CurveChildLiquidityGaugeRewardTokenStrategy,
) {}

async getRewardOnlyGaugePositions() {
async getRewardsOnlyGaugePositions() {
const definitions = [CURVE_V1_POOL_DEFINITIONS, CURVE_V2_POOL_DEFINITIONS].flat().filter(v => !!v.gaugeAddress);

return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<CurveRewardsOnlyGauge>({
Expand Down Expand Up @@ -84,7 +84,7 @@ export class PolygonCurveFarmContractPositionFetcher implements PositionFetcher<

async getPositions() {
const [rewardOnlyGaugePositions, childLiquidityGaugePositions] = await Promise.all([
this.getRewardOnlyGaugePositions(),
this.getRewardsOnlyGaugePositions(),
this.getChildLiquidityGaugePositions(),
]);

Expand Down

0 comments on commit a9c218e

Please sign in to comment.