UNPKG

@indigo-labs/indigo-sdk

Version:

Indigo SDK for interacting with Indigo endpoints via lucid-evolution

59 lines (57 loc) 2.19 kB
import { match, P } from 'ts-pattern'; import { Rational } from '../../types/rational'; import { decodePriceUpdate, decodePythMessage } from '../../utils/pyth'; import { DerivedPythPrice, fromDataDerivedPythPrice, PythConfiguration, } from './types'; import { ParsedFeedPayload } from '@pythnetwork/pyth-lazer-sdk'; import { fromHex } from '@lucid-evolution/lucid'; /** Rational form { num, den } so we can do exact division (e.g. 1/0.00001 = 100000). */ export function derivePythPrice( derivedPythPrice: DerivedPythPrice, messageHex: string, ): Rational { const decodedMessage = decodePythMessage(fromHex(messageHex)); const pricePayload = decodePriceUpdate(decodedMessage.payload); return match(derivedPythPrice) .with( { Value: P.select() }, (value: { configuration: PythConfiguration }) => { const payload = pricePayload.priceFeeds.find( (p: ParsedFeedPayload) => p.priceFeedId === Number(value.configuration.priceFeedId), ); if (!payload) throw new Error( `Pyth payload not found for feed ID: ${value.configuration.priceFeedId}`, ); const priceStr = payload.price; if (priceStr === undefined) throw new Error(`Pyth feed ${payload.priceFeedId} has no price`); const price = BigInt(priceStr); const exp = payload.exponent ?? 0; if (exp >= 0) { return { numerator: price * 10n ** BigInt(exp), denominator: 1n }; } return { numerator: price, denominator: 10n ** BigInt(-exp) }; }, ) .with({ Inverse: P.select() }, (inverse) => { const inner = derivePythPrice( fromDataDerivedPythPrice(inverse.value), messageHex, ); return { numerator: inner.denominator, denominator: inner.numerator }; }) .with({ Divide: P.select() }, (divide) => { const x = derivePythPrice(fromDataDerivedPythPrice(divide.x), messageHex); const y = derivePythPrice(fromDataDerivedPythPrice(divide.y), messageHex); return { numerator: x.numerator * y.denominator, denominator: x.denominator * y.numerator, }; }) .exhaustive(); }