Skip to content

Commit

Permalink
refactor: use prices api for lending price oracle ohlc
Browse files Browse the repository at this point in the history
  • Loading branch information
Alunara committed Jan 29, 2025
1 parent 578e1fa commit 225393c
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 53 deletions.
100 changes: 48 additions & 52 deletions apps/main/src/lend/store/createOhlcChartSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
} from 'ui/src/Chart/types'
import type { UTCTimestamp } from 'lightweight-charts'
import type { Address, Chain } from '@curvefi/prices-api'
import { getOracle } from '@curvefi/prices-api/lending'
import { getOHLC } from '@curvefi/prices-api/llamma'

import produce from 'immer'
Expand Down Expand Up @@ -405,41 +406,36 @@ const createOhlcChart = (set: SetState<State>, get: GetState<State>) => ({
const checkSummedController = getAddress(controller)

try {
const oracleOhlcDataFetch = await fetch(
`https://prices.curve.fi/v1/lending/oracle_ohlc/${network}/${checkSummedController}?agg_number=${interval}&agg_units=${timeUnit}&start=${start}&end=${end}`,
)
const oracleOhlcResponse = await oracleOhlcDataFetch.json()

// detail appears when no curve oracle pools can be found in the api
if (oracleOhlcResponse.detail) {
throw new Error(oracleOhlcResponse.detail)
}
const { pools, ohlc } = await getOracle({
chain: network as Chain,
controller: checkSummedController as Address,
interval,
units: timeUnit as OHLCTimeUnit,
start,
end,
})

if (oracleOhlcResponse.data?.length === 0) {
if (ohlc.length === 0) {
throw new Error('No oracle OHLC data found. Data may be unavailable for this pool.')
}

let baselinePriceArray: LlamaBaselinePriceData[] = []
let oraclePriceArray: OraclePriceData[] = []
let ohlcDataArray: LpPriceOhlcDataFormatted[] = []

for (const item of oracleOhlcResponse.data) {
if (item.base_price) {
baselinePriceArray.push({
time: convertToLocaleTimestamp(item.time) as UTCTimestamp,
base_price: item.base_price,
})
}
for (const item of ohlc) {
baselinePriceArray.push({
time: item.time.getUTCTimestamp(),
base_price: item.basePrice,
})

if (item.oracle_price) {
oraclePriceArray.push({
time: convertToLocaleTimestamp(item.time) as UTCTimestamp,
value: item.oracle_price,
})
}
oraclePriceArray.push({
time: item.time.getUTCTimestamp(),
value: item.oraclePrice,
})

ohlcDataArray.push({
time: convertToLocaleTimestamp(item.time) as UTCTimestamp,
time: item.time.getUTCTimestamp(),
open: item.open,
close: item.close,
high: item.high,
Expand All @@ -451,17 +447,17 @@ const createOhlcChart = (set: SetState<State>, get: GetState<State>) => ({
produce((state: State) => {
state[sliceKey].chartOraclePoolOhlc.data = ohlcDataArray
state[sliceKey].chartOraclePoolOhlc.collateralToken = {
address: oracleOhlcResponse.oracle_pools[0].collateral_address,
symbol: oracleOhlcResponse.oracle_pools[0].collateral_symbol,
address: pools[0].collateralAddress,
symbol: pools[0].collateralSymbol,
}
state[sliceKey].chartOraclePoolOhlc.borrowedToken = {
address: oracleOhlcResponse.oracle_pools[oracleOhlcResponse.oracle_pools.length - 1].borrowed_address,
symbol: oracleOhlcResponse.oracle_pools[oracleOhlcResponse.oracle_pools.length - 1].borrowed_symbol,
address: pools[pools.length - 1].borrowedAddress,
symbol: pools[pools.length - 1].borrowedSymbol,
}
state[sliceKey].chartOraclePoolOhlc.oraclePriceData = oraclePriceArray
state[sliceKey].chartOraclePoolOhlc.baselinePriceData = baselinePriceArray
state[sliceKey].chartOraclePoolOhlc.refetchingCapped = ohlcDataArray.length < 299
state[sliceKey].chartOraclePoolOhlc.lastFetchEndTime = oracleOhlcResponse.data[0].time
state[sliceKey].chartOraclePoolOhlc.lastFetchEndTime = ohlc[0].time.getUTCTimestamp()
state[sliceKey].chartOraclePoolOhlc.fetchStatus = 'READY'
}),
)
Expand Down Expand Up @@ -496,32 +492,32 @@ const createOhlcChart = (set: SetState<State>, get: GetState<State>) => ({
const checkSummedController = getAddress(controller)

try {
const oracleOhlcDataFetch = await fetch(
`https://prices.curve.fi/v1/lending/oracle_ohlc/${network}/${checkSummedController}?agg_number=${interval}&agg_units=${timeUnit}&start=${start}&end=${end}`,
)
const oracleOhlcResponse = await oracleOhlcDataFetch.json()
const { pools, ohlc } = await getOracle({
chain: network as Chain,
controller: checkSummedController as Address,
interval,
units: timeUnit as OHLCTimeUnit,
start,
end,
})

let baselinePriceArray: LlamaBaselinePriceData[] = []
let oraclePriceArray: OraclePriceData[] = []
let ohlcDataArray: LpPriceOhlcDataFormatted[] = []

for (const item of oracleOhlcResponse.data) {
if (item.base_price) {
baselinePriceArray.push({
time: convertToLocaleTimestamp(item.time) as UTCTimestamp,
base_price: item.base_price,
})
}
for (const item of ohlc) {
baselinePriceArray.push({
time: item.time.getUTCTimestamp(),
base_price: item.basePrice,
})

if (item.oracle_price) {
oraclePriceArray.push({
time: convertToLocaleTimestamp(item.time) as UTCTimestamp,
value: item.oracle_price,
})
}
oraclePriceArray.push({
time: item.time.getUTCTimestamp(),
value: item.oraclePrice,
})

ohlcDataArray.push({
time: convertToLocaleTimestamp(item.time) as UTCTimestamp,
time: item.time.getUTCTimestamp(),
open: item.open,
close: item.close,
high: item.high,
Expand All @@ -534,14 +530,14 @@ const createOhlcChart = (set: SetState<State>, get: GetState<State>) => ({
oracleData: oraclePriceArray,
baselineData: baselinePriceArray,
refetchingCapped: ohlcDataArray.length < 299,
lastFetchEndTime: oracleOhlcResponse.data[0].time,
lastFetchEndTime: ohlc[0].time.getUTCTimestamp(),
collateralToken: {
address: oracleOhlcResponse.oracle_pools[0].collateral_address,
symbol: oracleOhlcResponse.oracle_pools[0].collateral_symbol,
address: pools[0].collateralAddress,
symbol: pools[0].collateralSymbol,
},
borrowedToken: {
address: oracleOhlcResponse.oracle_pools[oracleOhlcResponse.oracle_pools.length - 1].borrowed_address,
symbol: oracleOhlcResponse.oracle_pools[oracleOhlcResponse.oracle_pools.length - 1].borrowed_symbol,
address: pools[pools.length - 1].borrowedAddress,
symbol: pools[pools.length - 1].borrowedSymbol,
},
}
} catch (error) {
Expand Down
34 changes: 33 additions & 1 deletion packages/prices-api/src/lending/api.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getHost, type Options, type Chain } from '..'
import { getHost, type Options, type Chain, type Address } from '..'
import { fetchJson as fetch } from '../fetch'
import type * as Responses from './responses'
import * as Parsers from './parsers'
Expand All @@ -13,3 +13,35 @@ export async function getLoanDistribution(endpoint: Endpoint, chain: Chain, cont

return Parsers.parseLoanDistribution(resp)
}

type GetOracleParams = {
chain: Chain
controller: Address
interval: number
units?: 'day' | 'hour' | 'minute'
start?: number
end?: number
}

export async function getOracle(
{ chain, controller, interval, units = 'hour', start, end }: GetOracleParams,
options?: Options,
) {
const host = getHost(options)

end ??= Math.floor(new Date().getTime() / 1000)
start ??= end - 10 * 24 * 60 * 60 // Subtract 1 month worth of seconds.

const params = new URLSearchParams({
agg_number: interval.toString(),
agg_units: units,
...(start && { start: start.toString() }),
...(end && { end: end.toString() }),
})

const resp = await fetch<Responses.GetOracleResponse>(
`${host}/v1/lending/oracle_ohlc/${chain}/${controller}?${params.toString()}`,
)

return Parsers.parseOracle(resp)
}
30 changes: 30 additions & 0 deletions packages/prices-api/src/lending/models.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { Address, Chain } from '..'

type Bar = {
value: number
label: string
Expand All @@ -8,3 +10,31 @@ export type LoanDistribution = {
debt: Bar[]
collateral: Bar[]
}

export type Oracle = {
chain: Chain
controller: Address
oracle: Address
pools: OraclePool[]
ohlc: OracleOHLC[]
}

export type OraclePool = {
address: Address
borrowedIndex: number
borrowedSymbol: string
borrowedAddress: Address
collateralIndex: number
collateralSymbol: string
collateralAddress: Address
}

export type OracleOHLC = {
time: Date
open: number
close: number
high: number
low: number
basePrice: number
oraclePrice: number
}
25 changes: 25 additions & 0 deletions packages/prices-api/src/lending/parsers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
import type * as Responses from './responses'
import type * as Models from './models'
import { toUTC } from '../timestamp'

export const parseLoanDistribution = (x: Responses.GetLoanDistributionResponse): Models.LoanDistribution => ({
stablecoin: x.stablecoin.map((x) => ({ value: x.value, label: x.label })),
debt: x.debt.map((x) => ({ value: x.value, label: x.label })),
collateral: x.collateral.map((x) => ({ value: x.value, label: x.label })),
})

export const parseOracle = (x: Responses.GetOracleResponse): Models.Oracle => ({
chain: x.chain,
controller: x.controller,
oracle: x.oracle,
pools: x.oracle_pools.map((pool) => ({
address: pool.address,
borrowedIndex: pool.borrowed_ix,
borrowedSymbol: pool.borrowed_symbol,
borrowedAddress: pool.borrowed_address,
collateralIndex: pool.collateral_ix,
collateralSymbol: pool.collateral_symbol,
collateralAddress: pool.collateral_address,
})),
ohlc: x.data.map((ohlc) => ({
time: toUTC(ohlc.time),
open: ohlc.open,
close: ohlc.close,
high: ohlc.high,
low: ohlc.low,
basePrice: ohlc.base_price,
oraclePrice: ohlc.oracle_price,
})),
})
28 changes: 28 additions & 0 deletions packages/prices-api/src/lending/responses.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { Address, Chain } from '..'

type Bar = {
value: number
label: string
Expand All @@ -8,3 +10,29 @@ export type GetLoanDistributionResponse = {
debt: Bar[]
collateral: Bar[]
}

export type GetOracleResponse = {
chain: Chain
controller: Address
oracle: Address
oracle_pools: [
{
address: Address
borrowed_ix: number
borrowed_symbol: string
borrowed_address: Address
collateral_ix: number
collateral_symbol: string
collateral_address: Address
},
]
data: {
time: number
open: number
close: number
high: number
low: number
base_price: number
oracle_price: number
}[]
}

0 comments on commit 225393c

Please sign in to comment.