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

Commit

Permalink
feat(concave): Convert Concave to templates, reduce calls to Hasura
Browse files Browse the repository at this point in the history
  • Loading branch information
immasandwich committed Sep 24, 2022
1 parent c14d1d3 commit 866b703
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 238 deletions.
6 changes: 3 additions & 3 deletions src/apps/concave/concave.definition.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export const CONCAVE_DEFINITION = appDefinition({
url: 'https://concave.lol',

groups: {
lsdcnv: {
id: 'lsdcnv',
liquidStaking: {
id: 'liquid-staking',
type: GroupType.TOKEN,
label: 'LSDCNV',
label: 'Liquid Staking',
},
},

Expand Down
7 changes: 3 additions & 4 deletions src/apps/concave/concave.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ import { AbstractApp } from '~app/app.dynamic-module';

import { ConcaveAppDefinition, CONCAVE_DEFINITION } from './concave.definition';
import { ConcaveContractFactory } from './contracts';
import { EthereumConcaveBalanceFetcher } from './ethereum/concave.balance-fetcher';
import { EthereumConcaveLsdcnvContractPositionFetcher } from './ethereum/concave.lsdcnv.contract-position-fetcher';
import { EthereumConcaveLiquidStakingContractPositionFetcher } from './ethereum/concave.liquid-staking.contract-position-fetcher';

@Register.AppModule({
appId: CONCAVE_DEFINITION.id,
providers: [
ConcaveAppDefinition,
ConcaveContractFactory,
EthereumConcaveBalanceFetcher,
EthereumConcaveLsdcnvContractPositionFetcher,
// Ethereum
EthereumConcaveLiquidStakingContractPositionFetcher,
],
})
export class ConcaveAppModule extends AbstractApp() {}
120 changes: 0 additions & 120 deletions src/apps/concave/ethereum/concave.balance-fetcher.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import { Inject } from '@nestjs/common';
import { BigNumberish } from 'ethers';
import { getAddress } from 'ethers/lib/utils';
import { gql } from 'graphql-request';
import { sumBy } from 'lodash';
import moment from 'moment';

import { drillBalance } from '~app-toolkit';
import { IAppToolkit, APP_TOOLKIT } from '~app-toolkit/app-toolkit.interface';
import { PositionTemplate } from '~app-toolkit/decorators/position-template.decorator';
import { ContractType } from '~position/contract.interface';
import { DefaultDataProps } from '~position/display.interface';
import { ContractPositionBalance } from '~position/position-balance.interface';
import { MetaType } from '~position/position.interface';
import { isClaimable, isSupplied } from '~position/position.utils';
import { ContractPositionTemplatePositionFetcher } from '~position/template/contract-position.template.position-fetcher';
import { GetTokenBalancesParams, GetTokenDefinitionsParams } from '~position/template/contract-position.template.types';

import { ConcaveContractFactory, Lsdcnv } from '../contracts';

export type ConcaveStakingV1Lock = {
deposit: string;
maturity: number;
poolBalance: string;
poolID: number;
poolTerm: number;
positionID: number;
rewardDebt: string;
to: string;
};

export type ConcaveStakingV1LockData = {
logStakingV1_Lock: ConcaveStakingV1Lock[];
};

export const GET_STAKING_V1_LOCK_EVENTS = gql`
query GetStakingV1Locks($address: String!) {
logStakingV1_Lock(where: { to: { _eq: $address } }) {
deposit
maturity
poolBalance
poolID
poolTerm
positionID
rewardDebt
to
}
}
`;

export type ConcaveLsdcnvContractPositionDataProps = {
poolID: number;
deposit: string;
unlockTime: number;
tokenId: number;
};

@PositionTemplate()
export class EthereumConcaveLiquidStakingContractPositionFetcher extends ContractPositionTemplatePositionFetcher<Lsdcnv> {
groupLabel = 'Liquid Staking';

constructor(
@Inject(APP_TOOLKIT) protected readonly appToolkit: IAppToolkit,
@Inject(ConcaveContractFactory) protected readonly concaveContractFactory: ConcaveContractFactory,
) {
super(appToolkit);
}

getContract(address: string): Lsdcnv {
return this.concaveContractFactory.lsdcnv({ address, network: this.network });
}

async getDefinitions() {
return [{ address: '0x93c3a816242e50ea8871a29bf62cc3df58787fbd' }];
}

async getTokenDefinitions(_params: GetTokenDefinitionsParams<Lsdcnv>) {
return [
{ metaType: MetaType.SUPPLIED, address: '0x000000007a58f5f58e697e51ab0357bc9e260a04' },
{ metaType: MetaType.CLAIMABLE, address: '0x000000007a58f5f58e697e51ab0357bc9e260a04' },
];
}

async getLabel() {
return 'Liquid Staked CNV';
}

getTokenBalancesPerPosition(_params: GetTokenBalancesParams<Lsdcnv, DefaultDataProps>): Promise<BigNumberish[]> {
throw new Error('Method not implemented.');
}

async getBalances(address: string): Promise<ContractPositionBalance<ConcaveLsdcnvContractPositionDataProps>[]> {
const multicall = this.appToolkit.getMulticall(this.network);
const [lsdCnv] = await this.appToolkit.getAppContractPositions({
appId: this.appId,
network: this.network,
groupIds: [this.groupId],
});

const contract = multicall.wrap(this.getContract(lsdCnv.address));
const balanceRaw = await contract.balanceOf(address);
if (Number(balanceRaw) === 0) return [];

const lockData = await this.appToolkit.helpers.theGraphHelper.requestGraph<ConcaveStakingV1LockData>({
endpoint: 'https://concave.hasura.app/v1/graphql',
query: GET_STAKING_V1_LOCK_EVENTS,
variables: { address: getAddress(address) },
});

const positions = await Promise.all(
lockData.logStakingV1_Lock.map(async event => {
const positionId = event.positionID;
const unlockDate = moment.unix(event.maturity).format('LL');
const label = `Liquid Staking (#${positionId}) - Unlock: ${unlockDate}`;

const [positionInfo, positionRewardInfo] = await Promise.all([
multicall.wrap(contract).positions(positionId),
multicall.wrap(contract).viewPositionRewards(positionId),
]);

const stakedToken = lsdCnv.tokens.find(isSupplied)!;
const rewardToken = lsdCnv.tokens.find(isClaimable)!;
const stakedTokenBalance = drillBalance(stakedToken, positionInfo.deposit.toString());
const rewardTokenBalance = drillBalance(rewardToken, positionRewardInfo.totalRewards.toString());
const tokens = [stakedTokenBalance, rewardTokenBalance];
const balanceUSD = sumBy(tokens, v => v.balanceUSD);

const position: ContractPositionBalance<ConcaveLsdcnvContractPositionDataProps> = {
type: ContractType.POSITION,
address: lsdCnv.address,
appId: lsdCnv.appId,
groupId: lsdCnv.groupId,
network: lsdCnv.network,
tokens,
balanceUSD,
dataProps: {
poolID: event.poolID,
deposit: event.deposit,
tokenId: event.positionID,
unlockTime: event.maturity,
},
displayProps: {
label,
images: lsdCnv.displayProps.images,
},
};

return position;
}),
);

return positions;
}
}

This file was deleted.

Loading

0 comments on commit 866b703

Please sign in to comment.