Pyth price fetching (#723)
* env: remove testing library * fix: use pyth over oracle * fix: fix the endpoints * fix: fix build * tidy: refactor * fix: fixed account fetching * fix: made all queries chain agnostic * fix: fixed the chart position
This commit is contained in:
parent
f1f934d4c1
commit
0960f84b58
@ -55,7 +55,6 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@svgr/webpack": "^8.1.0",
|
||||
"@testing-library/react": "^14.0.0",
|
||||
"@types/debounce-promise": "^3.1.9",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/lodash.throttle": "^4.1.8",
|
||||
|
@ -16,7 +16,7 @@ export default async function getAccount(
|
||||
const accountPosition: Positions = await cacheFn(
|
||||
() => creditManagerQueryClient.positions({ accountId: accountId }),
|
||||
positionsCache,
|
||||
`account/${accountId}`,
|
||||
`${chainConfig.id}/account/${accountId}`,
|
||||
)
|
||||
|
||||
const accountKind = await creditManagerQueryClient.accountKind({ accountId: accountId })
|
||||
|
@ -13,7 +13,7 @@ export default async function getAssetParams(
|
||||
return iterateContractQuery(paramsQueryClient.allAssetParams)
|
||||
},
|
||||
assetParamsCache,
|
||||
'assetParams',
|
||||
`${chainConfig.id}/assetParams`,
|
||||
600,
|
||||
)
|
||||
} catch (ex) {
|
||||
|
@ -19,7 +19,7 @@ export default async function getOraclePrices(
|
||||
const priceResults = await cacheFn(
|
||||
() => iterateContractQuery(oracleQueryClient.prices),
|
||||
oraclePriceCache,
|
||||
'oraclePrices',
|
||||
`${chainConfig.id}/oraclePrices`,
|
||||
60,
|
||||
)
|
||||
|
||||
|
@ -38,7 +38,7 @@ const getAssetRate = async (chainConfig: ChainConfig, asset: Asset) => {
|
||||
const response = await cacheFn(
|
||||
() => fetch(url).then((res) => res.json()),
|
||||
poolPriceCache,
|
||||
`poolPrices/${(asset.poolId || 0).toString()}`,
|
||||
`${chainConfig.id}/poolPrices/${(asset.poolId || 0).toString()}`,
|
||||
60,
|
||||
)
|
||||
const pool = response.pool
|
||||
|
@ -1,10 +1,7 @@
|
||||
import { cacheFn, priceCache } from 'api/cache'
|
||||
import { getOracleQueryClient } from 'api/cosmwasm-client'
|
||||
import getPoolPrice from 'api/prices/getPoolPrice'
|
||||
import getPythPrice from 'api/prices/getPythPrices'
|
||||
import { PRICE_ORACLE_DECIMALS } from 'constants/query'
|
||||
import getPrices from 'api/prices/getPrices'
|
||||
import { BN_ZERO } from 'constants/math'
|
||||
import { byDenom } from 'utils/array'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export default async function getPrice(
|
||||
chainConfig: ChainConfig,
|
||||
@ -15,25 +12,9 @@ export default async function getPrice(
|
||||
|
||||
async function fetchPrice(chainConfig: ChainConfig, denom: string) {
|
||||
try {
|
||||
const asset = chainConfig.assets.find(byDenom(denom)) as Asset
|
||||
const prices = await getPrices(chainConfig)
|
||||
|
||||
if (asset.pythPriceFeedId) {
|
||||
return (await getPythPrice(chainConfig, [asset.pythPriceFeedId]))[0]
|
||||
}
|
||||
|
||||
if (asset.hasOraclePrice) {
|
||||
const oracleQueryClient = await getOracleQueryClient(chainConfig)
|
||||
const priceResponse = await oracleQueryClient.price({ denom: asset.denom })
|
||||
const decimalDiff = asset.decimals - PRICE_ORACLE_DECIMALS
|
||||
|
||||
return BN(priceResponse.price).shiftedBy(decimalDiff)
|
||||
}
|
||||
|
||||
if (asset.poolId) {
|
||||
return await getPoolPrice(chainConfig, asset)
|
||||
}
|
||||
|
||||
throw `could not fetch the price info for the given denom: ${denom}`
|
||||
return prices.find(byDenom(denom))?.amount ?? BN_ZERO
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
|
@ -1,21 +1,18 @@
|
||||
import fetchPythPriceData from 'api/prices/getPythPriceData'
|
||||
|
||||
export default async function getPricesData(
|
||||
chainConfig: ChainConfig,
|
||||
assets: Asset[],
|
||||
): Promise<string[]> {
|
||||
export default async function getPricesData(assets: Asset[]): Promise<string[]> {
|
||||
try {
|
||||
const assetsWithPythPriceFeedId = assets.filter((asset) => !!asset.pythPriceFeedId)
|
||||
return await requestPythPriceData(chainConfig, assetsWithPythPriceFeedId)
|
||||
return await requestPythPriceData(assetsWithPythPriceFeedId)
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
async function requestPythPriceData(chainConfig: ChainConfig, assets: Asset[]): Promise<string[]> {
|
||||
async function requestPythPriceData(assets: Asset[]): Promise<string[]> {
|
||||
if (!assets.length) return []
|
||||
|
||||
const priceFeedIds = assets.map((a) => a.pythPriceFeedId) as string[]
|
||||
return await fetchPythPriceData(chainConfig, priceFeedIds)
|
||||
return await fetchPythPriceData(priceFeedIds)
|
||||
}
|
||||
|
@ -1,32 +1,35 @@
|
||||
import getOraclePrices from 'api/prices/getOraclePrices'
|
||||
import getPoolPrice from 'api/prices/getPoolPrice'
|
||||
import fetchPythPrices from 'api/prices/getPythPrices'
|
||||
import chains from 'configs/chains'
|
||||
import useStore from 'store'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { partition } from 'utils/array'
|
||||
import { getAllAssetsWithPythId } from 'utils/assets'
|
||||
|
||||
export default async function getPrices(chainConfig: ChainConfig): Promise<BNCoin[]> {
|
||||
const usdPrice = new BNCoin({ denom: 'usd', amount: '1' })
|
||||
try {
|
||||
const assetsToFetchPrices = useStore
|
||||
.getState()
|
||||
.chainConfig.assets.filter(
|
||||
(asset) => (asset.isEnabled && asset.isMarket) || asset.forceFetchPrice,
|
||||
)
|
||||
const [assetsWithPythPriceFeedId, assetsWithOraclePrices, assetsWithPoolIds] =
|
||||
separateAssetsByPriceSources(assetsToFetchPrices)
|
||||
|
||||
const pythAndOraclePrices = (
|
||||
await Promise.all([
|
||||
requestPythPrices(chainConfig, assetsWithPythPriceFeedId),
|
||||
getOraclePrices(chainConfig, assetsWithOraclePrices),
|
||||
])
|
||||
).flat()
|
||||
const pythAndOraclePrices = []
|
||||
const assetsToFetchPrices = useStore
|
||||
.getState()
|
||||
.chainConfig.assets.filter(
|
||||
(asset) => (asset.isEnabled && asset.isMarket) || asset.forceFetchPrice,
|
||||
)
|
||||
|
||||
const assetsWithPythPriceFeedId = getAllAssetsWithPythId(chains)
|
||||
const pythPrices = await requestPythPrices(assetsWithPythPriceFeedId)
|
||||
pythAndOraclePrices.push(...pythPrices)
|
||||
|
||||
try {
|
||||
const [assetsWithOraclePrices, assetsWithPoolIds] =
|
||||
separateAssetsByPriceSources(assetsToFetchPrices)
|
||||
const oraclePrices = await getOraclePrices(chainConfig, assetsWithOraclePrices)
|
||||
const poolPrices = await requestPoolPrices(chainConfig, assetsWithPoolIds, pythAndOraclePrices)
|
||||
|
||||
useStore.setState({ isOracleStale: false })
|
||||
|
||||
return [...pythAndOraclePrices, ...poolPrices, usdPrice]
|
||||
return [...pythAndOraclePrices, ...oraclePrices, ...poolPrices, usdPrice]
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
let message = 'Unknown Error'
|
||||
@ -34,15 +37,17 @@ export default async function getPrices(chainConfig: ChainConfig): Promise<BNCoi
|
||||
if (message.includes('price publish time is too old'))
|
||||
useStore.setState({ isOracleStale: true })
|
||||
|
||||
throw ex
|
||||
return [...pythAndOraclePrices, usdPrice]
|
||||
}
|
||||
}
|
||||
|
||||
async function requestPythPrices(chainConfig: ChainConfig, assets: Asset[]): Promise<BNCoin[]> {
|
||||
async function requestPythPrices(assets: Asset[]): Promise<BNCoin[]> {
|
||||
if (!assets.length) return []
|
||||
|
||||
const priceFeedIds = assets.map((a) => a.pythPriceFeedId) as string[]
|
||||
return await fetchPythPrices(chainConfig, priceFeedIds).then(mapResponseToBnCoin(assets))
|
||||
const priceFeedIds = assets
|
||||
.map((a) => a.pythPriceFeedId)
|
||||
.filter((priceFeedId, index, array) => array.indexOf(priceFeedId) === index) as string[]
|
||||
return await fetchPythPrices(priceFeedIds, assets)
|
||||
}
|
||||
|
||||
async function requestPoolPrices(
|
||||
@ -55,24 +60,20 @@ async function requestPoolPrices(
|
||||
return await Promise.all(requests).then(mapResponseToBnCoin(assets))
|
||||
}
|
||||
|
||||
const mapResponseToBnCoin = (assets: Asset[]) => (prices: BigNumber[]) =>
|
||||
prices.map((price: BigNumber, index: number) =>
|
||||
const mapResponseToBnCoin = (assets: Asset[]) => (prices: BigNumber[]) => {
|
||||
return prices.map((price: BigNumber, index: number) =>
|
||||
BNCoin.fromDenomAndBigNumber(assets[index].denom, price),
|
||||
)
|
||||
}
|
||||
|
||||
function separateAssetsByPriceSources(assets: Asset[]) {
|
||||
// Only fetch Pyth prices for mainnet
|
||||
const [assetsWithPythPriceFeedId, assetsWithoutPythPriceFeedId] = partition(
|
||||
assets,
|
||||
(asset) => !!asset.pythPriceFeedId,
|
||||
)
|
||||
const assetsWithoutPythPriceFeedId = assets.filter((asset) => !asset.pythPriceFeedId)
|
||||
|
||||
// Don't get oracle price if it's not mainnet and there is a poolId
|
||||
const [assetsWithOraclePrice, assetsWithoutOraclePrice] = partition(
|
||||
assetsWithoutPythPriceFeedId,
|
||||
(asset) => asset.hasOraclePrice || !asset.poolId,
|
||||
)
|
||||
const assetsWithPoolId = assetsWithoutOraclePrice.filter((asset) => !!asset.poolId)
|
||||
|
||||
return [assetsWithPythPriceFeedId, assetsWithOraclePrice, assetsWithPoolId]
|
||||
return [assetsWithOraclePrice, assetsWithPoolId]
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { cacheFn, pythPriceCache } from 'api/cache'
|
||||
import { pythEndpoints } from 'constants/pyth'
|
||||
|
||||
export default async function fetchPythPriceData(chainConfig: ChainConfig, priceFeedIds: string[]) {
|
||||
export default async function fetchPythPriceData(priceFeedIds: string[]) {
|
||||
try {
|
||||
const pricesUrl = new URL(`${chainConfig.endpoints.pyth}/latest_vaas`)
|
||||
const pricesUrl = new URL(`${pythEndpoints.api}/latest_vaas`)
|
||||
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
|
||||
|
||||
const pythDataResponse: string[] = await cacheFn(
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { cacheFn, pythPriceCache } from 'api/cache'
|
||||
import { pythEndpoints } from 'constants/pyth'
|
||||
import { BNCoin } from 'types/classes/BNCoin'
|
||||
import { BN } from 'utils/helpers'
|
||||
|
||||
export default async function fetchPythPrices(chainConfig: ChainConfig, priceFeedIds: string[]) {
|
||||
export default async function fetchPythPrices(priceFeedIds: string[], assets: Asset[]) {
|
||||
try {
|
||||
const pricesUrl = new URL(`${chainConfig.endpoints.pyth}/latest_price_feeds`)
|
||||
const pricesUrl = new URL(`${pythEndpoints.api}/latest_price_feeds`)
|
||||
priceFeedIds.forEach((id) => pricesUrl.searchParams.append('ids[]', id))
|
||||
|
||||
const pythResponse: PythPriceData[] = await cacheFn(
|
||||
@ -13,7 +15,18 @@ export default async function fetchPythPrices(chainConfig: ChainConfig, priceFee
|
||||
30,
|
||||
)
|
||||
|
||||
return pythResponse.map(({ price }) => BN(price.price).shiftedBy(price.expo))
|
||||
const mappedPriceData = [] as BNCoin[]
|
||||
|
||||
assets.forEach((asset) => {
|
||||
const price = pythResponse.find((pythPrice) => asset.pythPriceFeedId === pythPrice.id)?.price
|
||||
if (price)
|
||||
mappedPriceData.push(
|
||||
BNCoin.fromDenomAndBigNumber(asset.denom, BN(price.price).shiftedBy(price.expo)),
|
||||
)
|
||||
return
|
||||
})
|
||||
|
||||
return mappedPriceData
|
||||
} catch (ex) {
|
||||
throw ex
|
||||
}
|
||||
|
@ -5,12 +5,17 @@ export default async function getAprs(chainConfig: ChainConfig) {
|
||||
const response = await cacheFn(
|
||||
() => fetch(chainConfig.endpoints.aprs.vaults),
|
||||
aprsCacheResponse,
|
||||
'aprsResponse',
|
||||
`${chainConfig.id}/aprsResponse`,
|
||||
60,
|
||||
)
|
||||
|
||||
if (response.ok) {
|
||||
const data: AprResponse = await cacheFn(() => response.json(), aprsCache, 'aprs', 60)
|
||||
const data: AprResponse = await cacheFn(
|
||||
() => response.json(),
|
||||
aprsCache,
|
||||
`${chainConfig.id}/aprs`,
|
||||
60,
|
||||
)
|
||||
|
||||
return data.vaults.map((aprData) => {
|
||||
const finalApr = aprData.apr.projected_apr * 100
|
||||
|
@ -11,7 +11,7 @@ export const getVaultConfigs = async (
|
||||
return await cacheFn(
|
||||
() => iterateContractQuery(paramsQueryClient.allVaultConfigs, 'addr'),
|
||||
vaultConfigsCache,
|
||||
'vaultConfigs',
|
||||
`${chainConfig.id}/vaultConfigs`,
|
||||
600,
|
||||
)
|
||||
} catch (ex) {
|
||||
|
@ -15,7 +15,6 @@ export default async function getAccounts(
|
||||
.map((account) => getAccount(chainConfig, account.id))
|
||||
|
||||
const accounts = await Promise.all($accounts).then((accounts) => accounts)
|
||||
|
||||
if (accounts) {
|
||||
return accounts.sort((a, b) => Number(a.id) - Number(b.id))
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { defaultSymbolInfo } from 'components/Trade/TradeChart/constants'
|
||||
import { MILLISECONDS_PER_MINUTE } from 'constants/math'
|
||||
import { pythEndpoints } from 'constants/pyth'
|
||||
import { byDenom } from 'utils/array'
|
||||
import {
|
||||
Bar,
|
||||
@ -74,7 +75,7 @@ export class DataFeed implements IDatafeedChartApi {
|
||||
chainConfig: ChainConfig,
|
||||
) {
|
||||
if (debug) console.log('Start charting library datafeed')
|
||||
this.candlesEndpoint = chainConfig.endpoints.pythCandles
|
||||
this.candlesEndpoint = pythEndpoints.candles
|
||||
this.candlesEndpointTheGraph = chainConfig.endpoints.graphCandles ?? ''
|
||||
this.assets = assets
|
||||
this.debug = debug
|
||||
|
@ -160,7 +160,7 @@ export const TVChartContainer = (props: Props) => {
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
contentClassName='px-0.5 pb-0.5 h-full bg-chart'
|
||||
contentClassName='px-0.5 pb-0.5 h-full bg-chart w-[calc(100%-2px)] ml-[1px]'
|
||||
className='h-[70dvh] max-h-[980px] min-h-[560px]'
|
||||
>
|
||||
<div ref={chartContainerRef} className='h-[calc(100%-32px)] overflow-hidden' />
|
||||
|
@ -45,7 +45,7 @@ export default function TradeChart(props: Props) {
|
||||
<Loading className='h-4 mr-4 w-60' />
|
||||
</div>
|
||||
}
|
||||
contentClassName='px-0.5 pb-0.5 h-full'
|
||||
contentClassName='px-0.5 pb-0.5 h-full bg-chart w-[calc(100%-2px)] ml-[1px]'
|
||||
className='h-[70dvh] max-h-[980px] min-h-[560px]'
|
||||
>
|
||||
<div className='flex items-center justify-center w-full h-[calc(100%-32px)] rounded-b-base bg-chart'>
|
||||
|
@ -35,8 +35,6 @@ const Pion1: ChainConfig = {
|
||||
rest: 'https://rest-palvus.pion-1.ntrn.tech/',
|
||||
rpc: 'https://rpc-palvus.pion-1.ntrn.tech/',
|
||||
swap: 'https://testnet-neutron.astroport.fi/swap',
|
||||
pyth: 'https://hermes.pyth.network/api',
|
||||
pythCandles: 'https://benchmarks.pyth.network',
|
||||
pools: '', //TODO: ⛓️ Implement this
|
||||
explorer: 'https://testnet.mintscan.io/neutron-testnet',
|
||||
aprs: {
|
||||
|
@ -134,8 +134,6 @@ const Osmosis1: ChainConfig = {
|
||||
rpc: 'https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-rpc-front/',
|
||||
rest: 'https://osmosis-node.marsprotocol.io/GGSFGSFGFG34/osmosis-lcd-front/',
|
||||
swap: 'https://app.osmosis.zone',
|
||||
pyth: 'https://hermes.pyth.network/api',
|
||||
pythCandles: 'https://benchmarks.pyth.network',
|
||||
graphCandles: 'https://osmosis-candles.marsprotocol.io',
|
||||
explorer: 'https://www.mintscan.io/osmosis/transactions/',
|
||||
pools:
|
||||
|
4
src/constants/pyth.ts
Normal file
4
src/constants/pyth.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export const pythEndpoints = {
|
||||
api: 'https://hermes.pyth.network/api',
|
||||
candles: 'https://benchmarks.pyth.network',
|
||||
}
|
@ -7,7 +7,7 @@ import useStore from 'store'
|
||||
export default function usePricesData() {
|
||||
const assets = useStore((s) => s.chainConfig.assets)
|
||||
const chainConfig = useChainConfig()
|
||||
return useSWR(`chains/${chainConfig.id}/pricesData`, () => getPricesData(chainConfig, assets), {
|
||||
return useSWR(`chains/${chainConfig.id}/pricesData`, () => getPricesData(assets), {
|
||||
fallbackData: [],
|
||||
refreshInterval: 30_000,
|
||||
revalidateOnFocus: false,
|
||||
|
2
src/types/interfaces/chain.d.ts
vendored
2
src/types/interfaces/chain.d.ts
vendored
@ -27,8 +27,6 @@ interface ChainConfig {
|
||||
rest: string
|
||||
rpc: string
|
||||
swap: string
|
||||
pyth: string
|
||||
pythCandles: string
|
||||
graphCandles?: string
|
||||
explorer: string
|
||||
pools: string
|
||||
|
@ -45,3 +45,14 @@ export function sortAssetsOrPairs(
|
||||
return bMarketValue - aMarketValue
|
||||
})
|
||||
}
|
||||
|
||||
export function getAllAssetsWithPythId(chains: { [key: string]: ChainConfig }) {
|
||||
return Object.entries(chains)
|
||||
.map(([_, chainConfig]) => chainConfig.assets)
|
||||
.flatMap((assets) => assets)
|
||||
.filter(
|
||||
(item, index, array) =>
|
||||
index === array.findIndex((foundItem) => foundItem['denom'] === item['denom']),
|
||||
)
|
||||
.filter((asset) => asset.pythPriceFeedId)
|
||||
}
|
||||
|
@ -78,6 +78,7 @@ export function resolveHLSStrategies(
|
||||
}
|
||||
|
||||
export function resolvePerpsPositions(perpPositions: Positions['perps']): PerpsPosition[] {
|
||||
if (!perpPositions) return []
|
||||
return perpPositions.map((position) => {
|
||||
return {
|
||||
denom: position.denom,
|
||||
|
67
yarn.lock
67
yarn.lock
@ -39,7 +39,7 @@
|
||||
tslib "^2.3.0"
|
||||
zen-observable-ts "^1.2.5"
|
||||
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.21.4":
|
||||
"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.21.4":
|
||||
version "7.21.4"
|
||||
resolved "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.21.4.tgz"
|
||||
integrity sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==
|
||||
@ -1103,7 +1103,7 @@
|
||||
dependencies:
|
||||
regenerator-runtime "^0.13.11"
|
||||
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.20.7", "@babel/runtime@^7.8.4":
|
||||
"@babel/runtime@^7.1.2", "@babel/runtime@^7.20.7", "@babel/runtime@^7.8.4":
|
||||
version "7.21.5"
|
||||
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.5.tgz"
|
||||
integrity sha512-8jI69toZqqcsnqGGqwGS4Qb1VwLOEp4hz+CXPywcvjs60u3B4Pom/U/7rm4W8tMOYEB+E9wgD0mW1l3r8qlI9Q==
|
||||
@ -3406,29 +3406,6 @@
|
||||
long "^4.0.0"
|
||||
protobufjs "~6.11.2"
|
||||
|
||||
"@testing-library/dom@^9.0.0":
|
||||
version "9.2.0"
|
||||
resolved "https://registry.npmjs.org/@testing-library/dom/-/dom-9.2.0.tgz"
|
||||
integrity sha512-xTEnpUKiV/bMyEsE5bT4oYA0x0Z/colMtxzUY8bKyPXBNLn/e0V4ZjBZkEhms0xE4pv9QsPfSRu9AWS4y5wGvA==
|
||||
dependencies:
|
||||
"@babel/code-frame" "^7.10.4"
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@types/aria-query" "^5.0.1"
|
||||
aria-query "^5.0.0"
|
||||
chalk "^4.1.0"
|
||||
dom-accessibility-api "^0.5.9"
|
||||
lz-string "^1.5.0"
|
||||
pretty-format "^27.0.2"
|
||||
|
||||
"@testing-library/react@^14.0.0":
|
||||
version "14.0.0"
|
||||
resolved "https://registry.npmjs.org/@testing-library/react/-/react-14.0.0.tgz"
|
||||
integrity sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.12.5"
|
||||
"@testing-library/dom" "^9.0.0"
|
||||
"@types/react-dom" "^18.0.0"
|
||||
|
||||
"@tippyjs/react@^4.2.6":
|
||||
version "4.2.6"
|
||||
resolved "https://registry.npmjs.org/@tippyjs/react/-/react-4.2.6.tgz"
|
||||
@ -3441,11 +3418,6 @@
|
||||
resolved "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz"
|
||||
integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==
|
||||
|
||||
"@types/aria-query@^5.0.1":
|
||||
version "5.0.1"
|
||||
resolved "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.1.tgz"
|
||||
integrity sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==
|
||||
|
||||
"@types/bn.js@5.1.1", "@types/bn.js@^5.1.0":
|
||||
version "5.1.1"
|
||||
resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.1.tgz"
|
||||
@ -3581,7 +3553,7 @@
|
||||
resolved "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz"
|
||||
integrity sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==
|
||||
|
||||
"@types/react-dom@18.2.15", "@types/react-dom@^18.0.0":
|
||||
"@types/react-dom@18.2.15":
|
||||
version "18.2.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.15.tgz#921af67f9ee023ac37ea84b1bc0cc40b898ea522"
|
||||
integrity sha512-HWMdW+7r7MR5+PZqJF6YFNSCtjz1T0dsvo/f1BV6HkV+6erD/nA7wd9NM00KVG83zf2nJ7uATPO9ttdIPvi3gg==
|
||||
@ -3958,11 +3930,6 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
|
||||
dependencies:
|
||||
color-convert "^2.0.1"
|
||||
|
||||
ansi-styles@^5.0.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz"
|
||||
integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==
|
||||
|
||||
ansi-styles@^6.0.0, ansi-styles@^6.2.1:
|
||||
version "6.2.1"
|
||||
resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz"
|
||||
@ -3991,7 +3958,7 @@ argparse@^2.0.1:
|
||||
resolved "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
aria-query@^5.0.0, aria-query@^5.1.3:
|
||||
aria-query@^5.1.3:
|
||||
version "5.1.3"
|
||||
resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz"
|
||||
integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==
|
||||
@ -4429,7 +4396,7 @@ chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2:
|
||||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.1.0:
|
||||
chalk@^4.0.0:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz"
|
||||
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
|
||||
@ -4968,11 +4935,6 @@ doctrine@^3.0.0:
|
||||
dependencies:
|
||||
esutils "^2.0.2"
|
||||
|
||||
dom-accessibility-api@^0.5.9:
|
||||
version "0.5.16"
|
||||
resolved "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz"
|
||||
integrity sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==
|
||||
|
||||
dom-helpers@^3.4.0:
|
||||
version "3.4.0"
|
||||
resolved "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz"
|
||||
@ -6887,11 +6849,6 @@ lru-cache@^6.0.0:
|
||||
dependencies:
|
||||
yallist "^4.0.0"
|
||||
|
||||
lz-string@^1.5.0:
|
||||
version "1.5.0"
|
||||
resolved "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz"
|
||||
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
|
||||
|
||||
magic-string@^0.27.0:
|
||||
version "0.27.0"
|
||||
resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz"
|
||||
@ -7516,15 +7473,6 @@ prettier@^3.0.3:
|
||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz"
|
||||
integrity sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==
|
||||
|
||||
pretty-format@^27.0.2:
|
||||
version "27.5.1"
|
||||
resolved "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz"
|
||||
integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==
|
||||
dependencies:
|
||||
ansi-regex "^5.0.1"
|
||||
ansi-styles "^5.0.0"
|
||||
react-is "^17.0.1"
|
||||
|
||||
process-nextick-args@~2.0.0:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz"
|
||||
@ -7670,11 +7618,6 @@ react-is@^16.10.2, react-is@^16.13.1, react-is@^16.7.0:
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"
|
||||
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
|
||||
|
||||
react-is@^17.0.1:
|
||||
version "17.0.2"
|
||||
resolved "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz"
|
||||
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
|
||||
|
||||
react-lifecycles-compat@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user