Skip to content
This repository has been archived by the owner on Oct 10, 2023. It is now read-only.

Commit

Permalink
Savers apr + filled data (#2470)
Browse files Browse the repository at this point in the history
- [x] `useSynthConstants` hook to provide `maxSynthPerPoolDepthRD` (based on Mimirs `MAXSYNTHPERPOOLDEPTH` or `MaxSynthPerPoolDepth` (TN constant)
- [x] Update TN open api using latest fix https://gitlab.com/thorchain/thornode/-/commit/653029bc41dd928b702237552d29e10d094c7ad4
- [x] Helper `eqError`

Part of #2431
  • Loading branch information
veado authored Dec 5, 2022
1 parent 93c663b commit 37a0633
Show file tree
Hide file tree
Showing 10 changed files with 166 additions and 78 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"generate:types": "yarn generate:types:midgard && yarn generate:types:thornode",
"generate:types:midgard": "yarn clean:types:midgard && TS_POST_PROCESS_FILE=./node_modules/.bin/prettier openapi-generator-cli generate -i https://midgard.ninerealms.com/v2/swagger.json -g typescript-rxjs -o ./src/renderer/types/generated/midgard --reserved-words-mappings in=in --enable-post-process-file",
"clean:types:midgard": "rimraf ./src/renderer/types/generated/midgard",
"generate:types:thornode": "yarn clean:types:thornode && TS_POST_PROCESS_FILE=./node_modules/.bin/prettier openapi-generator-cli generate -i https://gitlab.com/thorchain/thornode/-/raw/6e10252deb6d65775c484b9fe8c5814195be44be/openapi/openapi.yaml -g typescript-rxjs -o ./src/renderer/types/generated/thornode --enable-post-process-file --skip-validate-spec",
"generate:types:thornode": "yarn clean:types:thornode && TS_POST_PROCESS_FILE=./node_modules/.bin/prettier openapi-generator-cli generate -i https://gitlab.com/thorchain/thornode/-/raw/653029bc41dd928b702237552d29e10d094c7ad4/openapi/openapi.yaml -g typescript-rxjs -o ./src/renderer/types/generated/thornode --enable-post-process-file --skip-validate-spec",
"clean:types:thornode": "rimraf ./src/renderer/types/generated/thornode",
"storybook": "sb dev -p 9009 --no-manager-cache",
"build-storybook": "sb build",
Expand Down
2 changes: 2 additions & 0 deletions src/renderer/helpers/fp/eq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ export const eqApiError = Eq.struct<ApiError>({
msg: eqString
})

export const eqError: Eq.Eq<Error> = { equals: (x, y) => x === y }

export const eqBalances = A.getEq(eqBalance)
export const eqAssetsWithAmount = A.getEq(eqAssetWithAmount)

Expand Down
23 changes: 16 additions & 7 deletions src/renderer/helpers/savers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getValueOfAsset1InAsset2, PoolData } from '@thorchain/asgardex-util'
import { assetFromString, BaseAmount, baseAmount } from '@xchainjs/xchain-util'
import { assetFromString, BaseAmount, baseAmount, bnOrZero } from '@xchainjs/xchain-util'
import * as A from 'fp-ts/lib/Array'
import * as FP from 'fp-ts/lib/function'
import * as O from 'fp-ts/lib/Option'
Expand Down Expand Up @@ -28,12 +28,13 @@ export const getSaversTableRowData = ({
poolDetail,
pricePoolData,
watchlist,
maxSynthPerPoolDepth,
network
}: {
// TODO(@veado) Update Midgard types
poolDetail: PoolDetail & { saversDepth?: string }
poolDetail: PoolDetail
pricePoolData: PoolData
watchlist: PoolsWatchList
maxSynthPerPoolDepth: number
network: Network
}): O.Option<SaversTableRowData> => {
return FP.pipe(
Expand All @@ -44,6 +45,13 @@ export const getSaversTableRowData = ({
const poolData = toPoolData(poolDetail)
const depthAmount = baseAmount(poolDetail.saversDepth)
const depthPrice = getValueOfAsset1InAsset2(depthAmount, poolData, pricePoolData)
const apr = bnOrZero(poolDetail.saversAPR).times(100)

const maxPercent = bnOrZero(maxSynthPerPoolDepth).div(100)
// saverCap = assetDepth * 2 * maxPercent / 100
const saverCap = bnOrZero(poolDetail.assetDepth).times(2).times(maxPercent).div(100)
// filled = saversDepth * 100 / saverCap
const filled = bnOrZero(poolDetail.saversDepth).times(100).div(saverCap)

const watched: boolean = FP.pipe(
watchlist,
Expand All @@ -55,11 +63,10 @@ export const getSaversTableRowData = ({
asset: poolDetailAsset,
depth: depthAmount,
depthPrice,
filled: 0, // TODO(@veado) Get dat from extra data
count: 0, // TODO(@veado) Get dat from extra data
filled,
key: poolDetailAsset.ticker,
network,
apr: 0, // get APR
apr,
watched
}
})
Expand All @@ -70,11 +77,13 @@ export const getSaversTableRowsData = ({
poolDetails,
pricePoolData,
watchlist,
maxSynthPerPoolDepth,
network
}: {
poolDetails: PoolDetails
pricePoolData: PoolData
watchlist: PoolsWatchList
maxSynthPerPoolDepth: number
network: Network
}): SaversTableRowsData => {
// get symbol of deepest pool
Expand All @@ -99,7 +108,7 @@ export const getSaversTableRowsData = ({
)

return FP.pipe(
getSaversTableRowData({ poolDetail, pricePoolData, watchlist, network }),
getSaversTableRowData({ poolDetail, pricePoolData, watchlist, maxSynthPerPoolDepth, network }),
O.map(
(poolTableRowData) =>
({
Expand Down
17 changes: 8 additions & 9 deletions src/renderer/hooks/usePoolCycle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,21 @@ export const usePoolCycle = (): {
poolCycle: PoolCycleRD
reloadPoolCycle: FP.Lazy<void>
} => {
const { mimir$, reloadMimir } = useThorchainContext()
const { thorchainConstantsState$, reloadThorchainConstants } = useThorchainContext()
const { mimir$, reloadMimir, thorchainConstantsState$, reloadThorchainConstants } = useThorchainContext()

const midgardConstantsPoolCycle$: PoolCycleLD = useMemo(
const tnConstantsPoolCycle$: PoolCycleLD = useMemo(
() =>
FP.pipe(
thorchainConstantsState$,
liveData.map(({ int64_values }) => Number(int64_values?.PoolCycle)),
liveData.map(({ int_64_values }) => Number(int_64_values?.PoolCycle)),
liveData.chain((poolCycle) =>
// validation -> value needs to be a number
liveData.fromPredicate<Error, number>(
() => !isNaN(poolCycle),
() => Error(`Invalid value of constant 'PoolCycle' ${poolCycle} `)
)(poolCycle)
),
liveData.mapLeft(() => ({ errorId: ErrorId.GET_POOL_CYCLE, msg: 'Unable to get constant of PoolCycle' }))
liveData.mapLeft(() => ({ errorId: ErrorId.GET_TC_CONSTANT, msg: 'Unable to get constant of PoolCycle' }))
),
[thorchainConstantsState$]
)
Expand All @@ -48,7 +47,7 @@ export const usePoolCycle = (): {
mimir$,
liveData.map(({ POOLCYCLE: poolCycle }) => O.fromNullable(poolCycle)),
liveData.chain(liveData.fromOption(() => Error('Unable to load pool cycle from Mimir'))),
liveData.mapLeft(({ message }) => ({ errorId: ErrorId.GET_POOL_CYCLE, msg: message }))
liveData.mapLeft(({ message }) => ({ errorId: ErrorId.GET_TC_CONSTANT, msg: message }))
),
[mimir$]
)
Expand All @@ -61,11 +60,11 @@ export const usePoolCycle = (): {
const [data] = useObservableState(
() =>
FP.pipe(
Rx.combineLatest([midgardConstantsPoolCycle$, mimirPoolCycle$]),
RxOp.map(([mimirPoolCycleRD, midgardPoolCycleRD]) =>
Rx.combineLatest([tnConstantsPoolCycle$, mimirPoolCycle$]),
RxOp.map(([tnPoolCycleRD, mimirPoolCycleRD]) =>
FP.pipe(
mimirPoolCycleRD,
RD.alt(() => midgardPoolCycleRD)
RD.alt(() => tnPoolCycleRD)
)
),
RxOp.distinctUntilChanged(eqPoolCycle.equals)
Expand Down
79 changes: 79 additions & 0 deletions src/renderer/hooks/useSynthConstants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { useCallback, useEffect, useMemo } from 'react'

import * as RD from '@devexperts/remote-data-ts'
import * as FP from 'fp-ts/function'
import * as N from 'fp-ts/lib/number'
import * as O from 'fp-ts/lib/Option'
import { useObservableState } from 'observable-hooks'
import * as Rx from 'rxjs'
import * as RxOp from 'rxjs/operators'

import { useThorchainContext } from '../contexts/ThorchainContext'
import { eqError } from '../helpers/fp/eq'
import { LiveData, liveData } from '../helpers/rx/liveData'

const eqMaxSynthPerPoolDepthRD = RD.getEq<Error, number>(eqError, N.Eq)

type MaxSynthPerPoolDepthRD = RD.RemoteData<Error, number>
type MaxSynthPerPoolDepthLD = LiveData<Error, number>

export const useSynthConstants = (): {
maxSynthPerPoolDepth: MaxSynthPerPoolDepthRD
reloadConstants: FP.Lazy<void>
} => {
const { mimir$, reloadMimir, thorchainConstantsState$, reloadThorchainConstants } = useThorchainContext()

const tnMaxSynthPerPoolDepth$: MaxSynthPerPoolDepthLD = useMemo(
() =>
FP.pipe(
thorchainConstantsState$,
liveData.map(({ int_64_values }) => Number(int_64_values?.MaxSynthPerPoolDepth)),
liveData.chain((value) =>
// validation -> value needs to be a number
liveData.fromPredicate<Error, number>(
() => !isNaN(value),
() => Error(`Invalid value of constant 'MaxSynthPerPoolDepth' ${value} `)
)(value)
)
),
[thorchainConstantsState$]
)

const mimirMaxSynthPerPoolDepth$: MaxSynthPerPoolDepthLD = useMemo(
() =>
FP.pipe(
mimir$,
liveData.map(({ MAXSYNTHPERPOOLDEPTH: poolCycle }) => O.fromNullable(poolCycle)),
liveData.chain(liveData.fromOption(() => Error(`Unable to get 'MAXSYNTHPERPOOLDEPTH' from Mimir`)))
),
[mimir$]
)

const getData = useCallback(() => {
reloadMimir()
reloadThorchainConstants()
}, [reloadThorchainConstants, reloadMimir])

const [data] = useObservableState(
() =>
FP.pipe(
Rx.combineLatest([mimirMaxSynthPerPoolDepth$, tnMaxSynthPerPoolDepth$]),
RxOp.map(([mimirMaxSynthPerPoolDepthRD, tnMaxSynthPerPoolDepthRD]) =>
FP.pipe(
mimirMaxSynthPerPoolDepthRD,
RD.alt(() => tnMaxSynthPerPoolDepthRD)
)
),
RxOp.distinctUntilChanged(eqMaxSynthPerPoolDepthRD.equals)
),
RD.initial
)

// Reload data on mount
useEffect(() => {
getData()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

return { maxSynthPerPoolDepth: data, reloadConstants: getData }
}
1 change: 1 addition & 0 deletions src/renderer/services/thorchain/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ export type ThornodeApiUrlRD = RD.RemoteData<Error, string>
export const MimirIO = t.type({
MAXIMUMLIQUIDITYRUNE: t.union([t.number, t.undefined]),
POOLCYCLE: t.union([t.number, t.undefined]),
MAXSYNTHPERPOOLDEPTH: t.union([t.number, t.undefined]),
HALTTRADING: t.union([t.number, t.undefined]),
HALTTHORCHAIN: t.union([t.number, t.undefined]),
HALTETHCHAIN: t.union([t.number, t.undefined]),
Expand Down
2 changes: 1 addition & 1 deletion src/renderer/services/wallet/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export enum ErrorId {
VALIDATE_NODE = 'VALIDATE_NODE',
VALIDATE_RESULT = 'VALIDATE_RESULT',
GET_ACTIONS = 'GET_ACTIONS',
GET_POOL_CYCLE = 'GET_POOL_CYCLE'
GET_TC_CONSTANT = 'GET_TC_CONSTANT'
}

export type ChainBalancesService = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export interface ConstantsResponse {
* @type {{ [key: string]: string; }}
* @memberof ConstantsResponse
*/
int64_values?: { [key: string]: string; };
int_64_values?: { [key: string]: string; };
/**
* @type {{ [key: string]: string; }}
* @memberof ConstantsResponse
Expand Down
6 changes: 3 additions & 3 deletions src/renderer/views/savers/Savers.types.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { BaseAmount, Asset } from '@xchainjs/xchain-util'
import BigNumber from 'bignumber.js'

import { Network } from '../../../shared/api/types'

export type SaversTableRowData = {
asset: Asset
depthPrice: BaseAmount
depth: BaseAmount
filled: number
count: number
apr: number
filled: BigNumber
apr: BigNumber
key: string
network: Network
watched: boolean
Expand Down
Loading

0 comments on commit 37a0633

Please sign in to comment.