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

Commit

Permalink
feat(jones-dao): Add staking V2, get staking V1 dynamically (#489)
Browse files Browse the repository at this point in the history
  • Loading branch information
immasandwich authored May 21, 2022
1 parent 5ee1f9a commit 8c47c93
Show file tree
Hide file tree
Showing 17 changed files with 4,813 additions and 59 deletions.
39 changes: 31 additions & 8 deletions src/apps/jones-dao/arbitrum/jones-dao.balance-fetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { Inject } from '@nestjs/common';
import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface';
import { Register } from '~app-toolkit/decorators';
import { presentBalanceFetcherResponse } from '~app-toolkit/helpers/presentation/balance-fetcher-response.present';
import { SynthetixContractFactory, SynthetixRewards } from '~apps/synthetix';
import { BalanceFetcher } from '~balance/balance-fetcher.interface';
import { Network } from '~types/network.interface';

import { JonesDaoContractFactory, JonesMillinerV2, JonesStakingRewards } from '../contracts';
import { JONES_DAO_DEFINITION } from '../jones-dao.definition';

const appId = JONES_DAO_DEFINITION.id;
Expand All @@ -16,22 +16,44 @@ const network = Network.ARBITRUM_MAINNET;
export class ArbitrumJonesDaoBalanceFetcher implements BalanceFetcher {
constructor(
@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit,
@Inject(SynthetixContractFactory)
private readonly synthetixContractFactory: SynthetixContractFactory,
@Inject(JonesDaoContractFactory)
private readonly contractFactory: JonesDaoContractFactory,
) {}

private async getStakedBalances(address: string) {
return this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances<SynthetixRewards>({
return this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances<JonesStakingRewards>({
appId,
network,
address,
groupId: JONES_DAO_DEFINITION.groups.farm.id,
resolveContract: ({ address, network }) => this.synthetixContractFactory.synthetixRewards({ address, network }),
resolveContract: ({ address, network }) => this.contractFactory.jonesStakingRewards({ address, network }),
resolveStakedTokenBalance: ({ contract, address, multicall }) => multicall.wrap(contract).balanceOf(address),
resolveRewardTokenBalances: ({ contract, address, multicall }) => multicall.wrap(contract).earned(address),
});
}

private async getStakedBalancesV2(address: string) {
return this.appToolkit.helpers.masterChefContractPositionBalanceHelper.getBalances<JonesMillinerV2>({
address,
network,
appId,
groupId: JONES_DAO_DEFINITION.groups.millinerV2.id,
resolveChefContract: ({ contractAddress }) =>
this.contractFactory.jonesMillinerV2({ network, address: contractAddress }),
resolveStakedTokenBalance: this.appToolkit.helpers.masterChefDefaultStakedBalanceStrategy.build({
resolveStakedBalance: ({ contract, multicall, contractPosition }) =>
multicall
.wrap(contract)
.userInfo(contractPosition.dataProps.poolIndex, address)
.then(v => v.amount),
}),
resolveClaimableTokenBalances: this.appToolkit.helpers.masterChefDefaultClaimableBalanceStrategy.build({
resolveClaimableBalance: ({ multicall, contract, contractPosition, address }) =>
multicall.wrap(contract).pendingJones(contractPosition.dataProps.poolIndex, address),
}),
});
}

private async getVaultBalances(address: string) {
return this.appToolkit.helpers.tokenBalanceHelper.getTokenBalances({
address,
Expand All @@ -42,9 +64,10 @@ export class ArbitrumJonesDaoBalanceFetcher implements BalanceFetcher {
}

async getBalances(address: string) {
const [stakedBalances, vaultBalances] = await Promise.all([
this.getStakedBalances(address),
const [vaultBalances, stakedBalances, stakedBalancesV2] = await Promise.all([
this.getVaultBalances(address),
this.getStakedBalances(address),
this.getStakedBalancesV2(address),
]);

return presentBalanceFetcherResponse([
Expand All @@ -54,7 +77,7 @@ export class ArbitrumJonesDaoBalanceFetcher implements BalanceFetcher {
},
{
label: 'Farms',
assets: stakedBalances,
assets: [...stakedBalances, ...stakedBalancesV2],
},
]);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,58 +1,16 @@
import { Inject } from '@nestjs/common';
import { compact, range } from 'lodash';

import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface';
import { Register } from '~app-toolkit/decorators';
import {
SynthetixContractFactory,
SynthetixRewards,
SynthetixSingleStakingIsActiveStrategy,
SynthetixSingleStakingRoiStrategy,
} from '~apps/synthetix';
import { SynthetixSingleStakingIsActiveStrategy, SynthetixSingleStakingRoiStrategy } from '~apps/synthetix';
import { PositionFetcher } from '~position/position-fetcher.interface';
import { ContractPosition } from '~position/position.interface';
import { Network } from '~types/network.interface';

import { JonesDaoContractFactory, JonesStakingRewards } from '../contracts';
import { JONES_DAO_DEFINITION } from '../jones-dao.definition';

const FARMS = [
// JONES StakingRewards
{
address: '0xf1a26Cf6309a59794da29B5b2E6fABD3070d470f',
stakedTokenAddress: '0x10393c20975cf177a3513071bc110f7962cd67da',
rewardTokenAddresses: ['0x10393c20975cf177a3513071bc110f7962cd67da'],
},
// JONES-ETH LP StakingRewards
{
address: '0x360a766f30f0ba57d2865efb32502fb800b14dd3',
stakedTokenAddress: '0xe8ee01ae5959d3231506fcdef2d5f3e85987a39c',
rewardTokenAddresses: ['0x10393c20975cf177a3513071bc110f7962cd67da'],
},
// JONES-USDC LP StakingRewards
{
address: '0x13f6a63867046107780bc3febdee90e7afcdfd99',
stakedTokenAddress: '0xa6efc26daa4bb2b9bf5d23a0bc202a2badc2b59e',
rewardTokenAddresses: ['0x10393c20975cf177a3513071bc110f7962cd67da'],
},
// jETH-ETH LP StakingRewards
{
address: '0xbac58e8b57935a0b60d5cb4cd9f6c21049595f04',
stakedTokenAddress: '0xdf1a6dd4e5b77d7f2143ed73074be26c806754c5',
rewardTokenAddresses: ['0x10393c20975cf177a3513071bc110f7962cd67da'],
},
// jgOHM-gOHM LP StakingRewards
{
address: '0x7ece38dbe9d61d0d9bf2d804a87a7d21b5937a56',
stakedTokenAddress: '0x292d1587a6bb37e34574c9ad5993f221d8a5616c',
rewardTokenAddresses: ['0x10393c20975cf177a3513071bc110f7962cd67da'],
},
// jDPX-DPX LP StakingRewards
{
address: '0x5723be83199c9ec68ed0ac979e98381224870e7f',
stakedTokenAddress: '0xeeb24360c8c7a87933d16b0075e10e1a30ad65b7',
rewardTokenAddresses: ['0x10393c20975cf177a3513071bc110f7962cd67da'],
},
];

const appId = JONES_DAO_DEFINITION.id;
const groupId = JONES_DAO_DEFINITION.groups.farm.id;
const network = Network.ARBITRUM_MAINNET;
Expand All @@ -61,28 +19,40 @@ const network = Network.ARBITRUM_MAINNET;
export class ArbitrumJonesDaoFarmContractPositionFetcher implements PositionFetcher<ContractPosition> {
constructor(
@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit,
@Inject(SynthetixContractFactory)
private readonly synthetixContractFactory: SynthetixContractFactory,
@Inject(JonesDaoContractFactory)
private readonly jonesDaoContractFactory: JonesDaoContractFactory,
@Inject(SynthetixSingleStakingIsActiveStrategy)
private readonly synthetixSingleStakingIsActiveStrategy: SynthetixSingleStakingIsActiveStrategy,
@Inject(SynthetixSingleStakingRoiStrategy)
private readonly synthetixSingleStakingRoiStrategy: SynthetixSingleStakingRoiStrategy,
) {}

async getPositions() {
return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<SynthetixRewards>({
const multicall = this.appToolkit.getMulticall(network);
const factoryAddress = '0x2c2082e4062bfd02141adc86cbd5e437201a1cf3';
const factory = this.jonesDaoContractFactory.jonesStakingRewardsFactory({ address: factoryAddress, network });
const mcf = multicall.wrap(factory);

const maybeStakingIds = await Promise.all(range(0, 50).map(i => mcf.stakingID(i).catch(() => null)));
const stakingIds = compact(maybeStakingIds).map(v => Number(v));
const stakingInfo = await Promise.all(stakingIds.map(i => mcf.stakingRewardsInfoByStakingToken(i)));
const stakingAddresses = stakingInfo.map(v => v.stakingRewards);

return this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<JonesStakingRewards>({
network,
appId,
groupId,
dependencies: [{ appId: 'sushiswap', groupIds: ['pool'], network }],
resolveFarmDefinitions: async () => FARMS,
resolveFarmContract: ({ network, address }) =>
this.synthetixContractFactory.synthetixRewards({ network, address }),
this.jonesDaoContractFactory.jonesStakingRewards({ network, address }),
resolveFarmAddresses: async () => stakingAddresses,
resolveStakedTokenAddress: async ({ multicall, contract }) => multicall.wrap(contract).stakingToken(),
resolveRewardTokenAddresses: async () => '0x10393c20975cf177a3513071bc110f7962cd67da',
resolveIsActive: this.synthetixSingleStakingIsActiveStrategy.build({
resolvePeriodFinish: ({ contract, multicall }) => multicall.wrap(contract).periodFinish(),
}),
resolveRois: this.synthetixSingleStakingRoiStrategy.build({
resolveRewardRates: ({ contract, multicall }) => multicall.wrap(contract).rewardRate(),
resolveRewardRates: ({ contract, multicall }) => multicall.wrap(contract).rewardRateJONES(),
}),
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { Inject } from '@nestjs/common';

import { APP_TOOLKIT, IAppToolkit } from '~app-toolkit/app-toolkit.interface';
import { Register } from '~app-toolkit/decorators';
import { RewardRateUnit } from '~app-toolkit/helpers/master-chef/master-chef.contract-position-helper';
import { PositionFetcher } from '~position/position-fetcher.interface';
import { ContractPosition } from '~position/position.interface';
import { Network } from '~types/network.interface';

import { JonesDaoContractFactory, JonesMillinerV2 } from '../contracts';
import { JONES_DAO_DEFINITION } from '../jones-dao.definition';

const appId = JONES_DAO_DEFINITION.id;
const groupId = JONES_DAO_DEFINITION.groups.millinerV2.id;
const network = Network.ARBITRUM_MAINNET;

@Register.ContractPositionFetcher({ appId, groupId, network })
export class ArbitrumJonesDaoMillinerV2ContractPositionFetcher implements PositionFetcher<ContractPosition> {
constructor(
@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit,
@Inject(JonesDaoContractFactory) private readonly contractFactory: JonesDaoContractFactory,
) {}

async getPositions() {
return this.appToolkit.helpers.masterChefContractPositionHelper.getContractPositions<JonesMillinerV2>({
address: '0xb94d1959084081c5a11c460012ab522f5a0fd756',
appId: JONES_DAO_DEFINITION.id,
groupId: JONES_DAO_DEFINITION.groups.millinerV2.id,
network: Network.ARBITRUM_MAINNET,
dependencies: [{ appId: 'sushiswap', groupIds: ['pool'], network }],
resolveContract: ({ address, network }) => this.contractFactory.jonesMillinerV2({ address, network }),
resolvePoolLength: ({ multicall, contract }) => multicall.wrap(contract).poolLength(),
resolveDepositTokenAddress: ({ poolIndex, contract, multicall }) =>
multicall
.wrap(contract)
.poolInfo(poolIndex)
.then(v => v.lpToken),
resolveRewardTokenAddresses: ({ multicall, contract }) => multicall.wrap(contract).jones(),
rewardRateUnit: RewardRateUnit.SECOND,
resolveRewardRate: this.appToolkit.helpers.masterChefDefaultRewardsPerBlockStrategy.build({
resolvePoolAllocPoints: async ({ poolIndex, contract, multicall }) =>
multicall
.wrap(contract)
.poolInfo(poolIndex)
.then(v => v.allocPoint),
resolveTotalAllocPoints: ({ multicall, contract }) => multicall.wrap(contract).totalAllocPoint(),
resolveTotalRewardRate: ({ multicall, contract }) => multicall.wrap(contract).jonesPerSecond(),
}),
});
}
}
Loading

0 comments on commit 8c47c93

Please sign in to comment.