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

Commit

Permalink
feat(plutus): Add Plutus DAO (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
tonzgao committed May 24, 2022
1 parent b2096de commit 26a0282
Show file tree
Hide file tree
Showing 26 changed files with 7,478 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/apps/plutus/arbitrum/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export const VAULTS = {
DPX_VAULT: '0x20DF4953BA19c74B2A46B6873803F28Bf640c1B5'.toLowerCase(),
JONES_VAULT: '0x23B87748b615096d1A0F48870daee203A720723D'.toLowerCase(),
PLS_VAULT: '0x5593473e318F0314Eb2518239c474e183c4cBED5'.toLowerCase(),
PLS_LOCK: '0xbeb981021ed9c85aa51d96c0c2eda10ee4404a2e'.toLowerCase(),
};

export const ADDRESSES = {
dpx: '0x6c2c06790b3e3e3c38e12ee22f8183b37a13ee55'.toLowerCase(),
rdpx: '0x32eb7902d4134bf98a28b963d26de779af92a212'.toLowerCase(),
jones: '0x10393c20975cf177a3513071bc110f7962cd67da'.toLowerCase(),
pls: '0x51318b7d00db7acc4026c88c3952b66278b6a67f'.toLowerCase(),
plsDpx: '0xf236ea74b515ef96a9898f5a4ed4aa591f253ce1'.toLowerCase(),
plsJones: '0xe7f6c3c1f0018e4c08acc52965e5cbff99e34a44'.toLowerCase(),
};
162 changes: 162 additions & 0 deletions src/apps/plutus/arbitrum/plutus.balance-fetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
import { Inject } from '@nestjs/common';

import { drillBalance } from '~app-toolkit';
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 { BalanceFetcher } from '~balance/balance-fetcher.interface';
import { MetaType } from '~position/position.interface';
import { Network } from '~types/network.interface';

import {
PlutusContractFactory,
PlsPlutusChef,
PlsDpxPlutusChef,
PlsJonesPlutusChef,
PlutusEpochStaking,
} from '../contracts';
import { PLUTUS_DEFINITION } from '../plutus.definition';

const appId = PLUTUS_DEFINITION.id;
const network = Network.ARBITRUM_MAINNET;

@Register.BalanceFetcher(PLUTUS_DEFINITION.id, network)
export class ArbitrumPlutusBalanceFetcher implements BalanceFetcher {
constructor(
@Inject(APP_TOOLKIT) private readonly appToolkit: IAppToolkit,
@Inject(PlutusContractFactory) private readonly contractFactory: PlutusContractFactory,
) {}

async getTokenBalances(address: string) {
return this.appToolkit.helpers.tokenBalanceHelper.getTokenBalances({
address,
network,
appId,
groupId: PLUTUS_DEFINITION.groups.ve.id,
});
}

async getLockedBalances(address: string) {
return this.appToolkit.helpers.singleStakingContractPositionBalanceHelper.getBalances<PlutusEpochStaking>({
address,
network,
appId,
groupId: PLUTUS_DEFINITION.groups.lock.id,
resolveContract: ({ address, network }) => this.contractFactory.plutusEpochStaking({ address, network }),
resolveStakedTokenBalance: ({ contract, address, multicall }) =>
multicall
.wrap(contract)
.stakedDetails(address)
.then(details => details.amount),
resolveRewardTokenBalances: () => [], // TODO: implement
});
}

async getStakedDPXBalances(address: string) {
return this.appToolkit.helpers.masterChefContractPositionBalanceHelper.getBalances<PlsDpxPlutusChef>({
address,
network,
appId,
groupId: PLUTUS_DEFINITION.groups.dpx.id,
resolveChefContract: ({ contractAddress, network }) =>
this.contractFactory.plsDpxPlutusChef({ address: contractAddress, network }),
resolveStakedTokenBalance: this.appToolkit.helpers.masterChefDefaultStakedBalanceStrategy.build({
resolveStakedBalance: ({ contract, multicall }) =>
multicall
.wrap(contract)
.userInfo(address)
.then(info => info.amount),
}),
resolveClaimableTokenBalances: async ({ address, contract, contractPosition, multicall }) => {
const pendingTokens = await multicall
.wrap(contract)
.userInfo(address)
.then(info => [
info.plsRewardDebt,
info.plsDpxRewardDebt,
info.plsJonesRewardDebt,
info.dpxRewardDebt,
info.rdpxRewardDebt,
]);
const claimableTokens = contractPosition.tokens.filter(t => t.metaType === MetaType.CLAIMABLE);
return claimableTokens.map((v, i) => drillBalance(v, pendingTokens[i].toString()));
},
});
}

async getStakedJonesBalances(address: string) {
return this.appToolkit.helpers.masterChefContractPositionBalanceHelper.getBalances<PlsJonesPlutusChef>({
address,
network,
appId,
groupId: PLUTUS_DEFINITION.groups.jones.id,
resolveChefContract: ({ contractAddress, network }) =>
this.contractFactory.plsJonesPlutusChef({ address: contractAddress, network }),
resolveStakedTokenBalance: this.appToolkit.helpers.masterChefDefaultStakedBalanceStrategy.build({
resolveStakedBalance: ({ contract, multicall }) =>
multicall
.wrap(contract)
.userInfo(address)
.then(info => info.amount),
}),
resolveClaimableTokenBalances: async ({ address, contract, contractPosition, multicall }) => {
const pendingTokens = await multicall
.wrap(contract)
.userInfo(address)
.then(info => [info.plsRewardDebt, info.plsDpxRewardDebt, info.plsJonesRewardDebt, info.jonesRewardDebt]);
const claimableTokens = contractPosition.tokens.filter(t => t.metaType === MetaType.CLAIMABLE);
return claimableTokens.map((v, i) => drillBalance(v, pendingTokens[i].toString()));
},
});
}

async getStakedPlsBalances(address: string) {
return this.appToolkit.helpers.masterChefContractPositionBalanceHelper.getBalances<PlsPlutusChef>({
address,
network,
appId,
groupId: PLUTUS_DEFINITION.groups.stake.id,
resolveChefContract: ({ contractAddress, network }) =>
this.contractFactory.plsPlutusChef({ address: contractAddress, network }),
resolveStakedTokenBalance: this.appToolkit.helpers.masterChefDefaultStakedBalanceStrategy.build({
resolveStakedBalance: ({ contractPosition, contract, multicall }) =>
multicall
.wrap(contract)
.userInfo(contractPosition.dataProps.poolIndex, address)
.then(info => info.amount),
}),
resolveClaimableTokenBalances: this.appToolkit.helpers.masterChefDefaultClaimableBalanceStrategy.build({
resolveClaimableBalance: ({ multicall, contract, contractPosition, address }) =>
multicall
.wrap(contract)
.userInfo(contractPosition.dataProps.poolIndex, address)
.then(info => info.rewardDebt),
}),
});
}

async getBalances(address: string) {
const [tokenBalances, lockedBalances, dpxBalances, jonesBalances, plsBalances] = await Promise.all([
this.getTokenBalances(address),
this.getStakedDPXBalances(address),
this.getStakedDPXBalances(address),
this.getStakedJonesBalances(address),
this.getStakedPlsBalances(address),
]);

return presentBalanceFetcherResponse([
{
label: 'Tokens',
assets: tokenBalances,
},
{
label: 'Locked',
assets: lockedBalances,
},
{
label: 'Staked',
assets: [...dpxBalances, ...jonesBalances, ...plsBalances],
},
]);
}
}
44 changes: 44 additions & 0 deletions src/apps/plutus/arbitrum/plutus.dpx.contract-position-fetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Inject } from '@nestjs/common';

import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface';
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 { PlutusContractFactory, PlsDpxPlutusChef } from '../contracts';
import { PLUTUS_DEFINITION } from '../plutus.definition';

import { ADDRESSES, VAULTS } from './consts';

const appId = PLUTUS_DEFINITION.id;
const groupId = PLUTUS_DEFINITION.groups.dpx.id;
const network = Network.ARBITRUM_MAINNET;

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

async getPositions() {
return this.appToolkit.helpers.masterChefContractPositionHelper.getContractPositions<PlsDpxPlutusChef>({
address: VAULTS.DPX_VAULT,
appId,
groupId,
network,
dependencies: [{ appId, groupIds: [PLUTUS_DEFINITION.groups.ve.id], network }],
resolveContract: opts => this.contractFactory.plsDpxPlutusChef(opts),
resolvePoolLength: async () => 1,
resolveDepositTokenAddress: async ({ multicall, contract }) => multicall.wrap(contract).plsDpx(),
resolveRewardTokenAddresses: async () => [
ADDRESSES.pls,
ADDRESSES.plsDpx,
ADDRESSES.plsJones,
ADDRESSES.dpx,
ADDRESSES.rdpx,
],
});
}
}
38 changes: 38 additions & 0 deletions src/apps/plutus/arbitrum/plutus.jones.contract-position-fetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Inject } from '@nestjs/common';

import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface';
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 { PlutusContractFactory, PlsJonesPlutusChef } from '../contracts';
import { PLUTUS_DEFINITION } from '../plutus.definition';

import { ADDRESSES, VAULTS } from './consts';

const appId = PLUTUS_DEFINITION.id;
const groupId = PLUTUS_DEFINITION.groups.jones.id;
const network = Network.ARBITRUM_MAINNET;

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

async getPositions() {
return this.appToolkit.helpers.masterChefContractPositionHelper.getContractPositions<PlsJonesPlutusChef>({
address: VAULTS.JONES_VAULT,
appId,
groupId,
network,
dependencies: [{ appId, groupIds: [PLUTUS_DEFINITION.groups.ve.id], network }],
resolveContract: opts => this.contractFactory.plsJonesPlutusChef(opts),
resolvePoolLength: async () => 1,
resolveDepositTokenAddress: async ({ multicall, contract }) => multicall.wrap(contract).plsJones(),
resolveRewardTokenAddresses: async () => [ADDRESSES.pls, ADDRESSES.plsDpx, ADDRESSES.plsJones, ADDRESSES.jones],
});
}
}
47 changes: 47 additions & 0 deletions src/apps/plutus/arbitrum/plutus.lock.contract-position-fetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Inject } from '@nestjs/common';

import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface';
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 { PlutusContractFactory, PlutusEpochStaking } from '../contracts';
import { PLUTUS_DEFINITION } from '../plutus.definition';

import { VAULTS } from './consts';

const appId = PLUTUS_DEFINITION.id;
const groupId = PLUTUS_DEFINITION.groups.lock.id;
const network = Network.ARBITRUM_MAINNET;

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

async getPositions() {
const positions =
this.appToolkit.helpers.singleStakingFarmContractPositionHelper.getContractPositions<PlutusEpochStaking>({
network,
appId,
groupId,
dependencies: [
{
appId,
groupIds: [groupId],
network,
},
],
resolveFarmAddresses: () => [VAULTS.PLS_LOCK],
resolveFarmContract: ({ address, network }) =>
this.plutusContractFactory.plutusEpochStaking({ address, network }),
resolveStakedTokenAddress: ({ contract, multicall }) => multicall.wrap(contract).pls(),
resolveRewardTokenAddresses: ({ contract, multicall }) => multicall.wrap(contract).stakingRewards(),
resolveRois: async () => ({ dailyROI: 0, weeklyROI: 0, yearlyROI: 0 }),
});
return positions;
}
}
53 changes: 53 additions & 0 deletions src/apps/plutus/arbitrum/plutus.stake.contract-position-fetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Inject } from '@nestjs/common';

import { IAppToolkit, APP_TOOLKIT } 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 { PlutusContractFactory, PlsPlutusChef } from '../contracts';
import { PLUTUS_DEFINITION } from '../plutus.definition';

import { VAULTS } from './consts';

const appId = PLUTUS_DEFINITION.id;
const groupId = PLUTUS_DEFINITION.groups.stake.id;
const network = Network.ARBITRUM_MAINNET;

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

async getPositions() {
return this.appToolkit.helpers.masterChefContractPositionHelper.getContractPositions<PlsPlutusChef>({
address: VAULTS.PLS_VAULT,
appId,
groupId,
network,
dependencies: [{ appId: 'sushiswap', groupIds: ['pool'], network }],
resolveContract: opts => this.contractFactory.plsPlutusChef(opts),
resolvePoolLength: ({ multicall, contract }) => multicall.wrap(contract).poolLength(),
resolveDepositTokenAddress: async ({ poolIndex, multicall, contract }) =>
multicall
.wrap(contract)
.poolInfo(poolIndex)
.then(info => info.lpToken),
resolveRewardTokenAddresses: ({ multicall, contract }) => multicall.wrap(contract).PLS(),
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).plsPerSecond(),
}),
});
}
}
Loading

0 comments on commit 26a0282

Please sign in to comment.