Add warning state if oracle is stale, convert last updated to human readable format

This commit is contained in:
Riordan Panayides 2023-04-27 17:23:18 +01:00
parent f122994874
commit c5dd4a0e82
1 changed files with 53 additions and 5 deletions

View File

@ -1,4 +1,7 @@
import { InformationCircleIcon } from '@heroicons/react/24/outline'
import {
ExclamationTriangleIcon,
InformationCircleIcon,
} from '@heroicons/react/24/outline'
import useSelectedMarket from 'hooks/useSelectedMarket'
import Tooltip from '@components/shared/Tooltip'
import { useTranslation } from 'next-i18next'
@ -15,6 +18,9 @@ import {
formatCurrencyValue,
getDecimalCount,
} from 'utils/numbers'
import dayjs from 'dayjs'
import duration from 'dayjs/plugin/duration'
import relativeTime from 'dayjs/plugin/relativeTime'
const OraclePrice = () => {
const {
@ -23,10 +29,16 @@ const OraclePrice = () => {
selectedMarket,
quoteBank,
} = useSelectedMarket()
dayjs.extend(duration)
dayjs.extend(relativeTime)
const connection = mangoStore((s) => s.connection)
const [price, setPrice] = useState(stalePrice)
const [oracleProviderName, setOracleProviderName] = useState('Unknown')
const [oracleLastUpdatedSlot, setOracleLastUpdatedSlot] = useState(0)
const [highestSlot, setHighestSlot] = useState(0)
const [isStale, setIsStale] = useState(false)
const { t } = useTranslation(['common', 'trade'])
//subscribe to the market oracle account
@ -65,7 +77,7 @@ const OraclePrice = () => {
const coder = new BorshAccountsCoder(client.program.idl)
const subId = connection.onAccountChange(
marketOrBank.oracle,
async (info, _context) => {
async (info, context) => {
// selectedMarket = mangoStore.getState().selectedMarket.current
// if (!(selectedMarket instanceof PerpMarket)) return
const { price, uiPrice, lastUpdatedSlot } =
@ -80,6 +92,22 @@ const OraclePrice = () => {
marketOrBank._uiPrice = uiPrice
marketOrBank._oracleLastUpdatedSlot = lastUpdatedSlot
setOracleLastUpdatedSlot(lastUpdatedSlot)
const marketSlot = mangoStore.getState().selectedMarket.lastSeenSlot
const oracleWriteSlot = context.slot
const accountSlot = mangoStore.getState().mangoAccount.lastSlot
const highestSlot = Math.max(
marketSlot.bids,
marketSlot.asks,
oracleWriteSlot,
accountSlot
)
setHighestSlot(highestSlot)
setIsStale(
highestSlot - lastUpdatedSlot >
marketOrBank.oracleConfig.maxStalenessSlots.toNumber()
)
if (selectedMarket instanceof PerpMarket) {
setPrice(uiPrice)
} else {
@ -108,10 +136,26 @@ const OraclePrice = () => {
<>
<div id="trade-step-two" className="flex-col whitespace-nowrap md:ml-6">
<Tooltip
placement="bottom"
content={
<>
<div>This price is provided by {oracleProviderName}</div>
<div>Last updated at slot {oracleLastUpdatedSlot}</div>
<div>This price is provided by {oracleProviderName}.</div>
<div className="mt-2">
Last updated{' '}
{dayjs
.duration({
seconds: -((highestSlot - oracleLastUpdatedSlot) * 0.5),
})
.humanize(true)}
.
</div>
{isStale ? (
<div className="mt-2 font-black">
This oracle has not updated recently.
<br />
Actions will fail for accounts with a position in this token.
</div>
) : undefined}
</>
}
>
@ -119,7 +163,11 @@ const OraclePrice = () => {
<div className="text-xs text-th-fgd-4">
{t('trade:oracle-price')}
</div>
<InformationCircleIcon className="ml-1 h-4 w-4 text-th-fgd-4" />
{isStale ? (
<ExclamationTriangleIcon className="ml-1 h-4 w-4 text-th-warning" />
) : (
<InformationCircleIcon className="ml-1 h-4 w-4 text-th-fgd-4" />
)}
</div>
</Tooltip>
<div className="font-mono text-xs text-th-fgd-2">