This repository has been archived by the owner on Jan 24, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 381
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(concave): Convert Concave to templates, reduce calls to Hasura
- Loading branch information
1 parent
c14d1d3
commit 866b703
Showing
8 changed files
with
175 additions
and
238 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
154 changes: 154 additions & 0 deletions
154
src/apps/concave/ethereum/concave.liquid-staking.contract-position-fetcher.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
84 changes: 0 additions & 84 deletions
84
src/apps/concave/ethereum/concave.lsdcnv.contract-position-fetcher.ts
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.