UNPKG

@pythnetwork/price-service-sdk

Version:
288 lines (287 loc) 11.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PriceFeed = exports.PriceFeedMetadata = exports.Price = exports.parseTwapMessage = exports.parsePriceFeedMessage = exports.parseAccumulatorUpdateData = exports.sliceAccumulatorUpdateData = exports.isAccumulatorUpdateData = void 0; const PriceFeed_1 = require("./schemas/PriceFeed"); var AccumulatorUpdateData_1 = require("./AccumulatorUpdateData"); Object.defineProperty(exports, "isAccumulatorUpdateData", { enumerable: true, get: function () { return AccumulatorUpdateData_1.isAccumulatorUpdateData; } }); Object.defineProperty(exports, "sliceAccumulatorUpdateData", { enumerable: true, get: function () { return AccumulatorUpdateData_1.sliceAccumulatorUpdateData; } }); Object.defineProperty(exports, "parseAccumulatorUpdateData", { enumerable: true, get: function () { return AccumulatorUpdateData_1.parseAccumulatorUpdateData; } }); Object.defineProperty(exports, "parsePriceFeedMessage", { enumerable: true, get: function () { return AccumulatorUpdateData_1.parsePriceFeedMessage; } }); Object.defineProperty(exports, "parseTwapMessage", { enumerable: true, get: function () { return AccumulatorUpdateData_1.parseTwapMessage; } }); /** * A Pyth Price represented as `${price} ± ${conf} * 10^${expo}` published at `publishTime`. */ class Price { conf; expo; price; publishTime; constructor(rawPrice) { this.conf = rawPrice.conf; this.expo = rawPrice.expo; this.price = rawPrice.price; this.publishTime = rawPrice.publishTime; } /** * Get price as number. Warning: this conversion might result in an inaccurate number. * We store price and confidence values in our Oracle at 64-bit precision, but the JavaScript * number type can only represent numbers with 52-bit precision. So if a price or confidence * is larger than 52-bits, the conversion will lose the most insignificant bits. * * @returns a floating point number representing the price */ getPriceAsNumberUnchecked() { return Number(this.price) * 10 ** this.expo; } /** * Get price as number. Warning: this conversion might result in an inaccurate number. * Explanation is the same as `priceAsNumberUnchecked()` documentation. * * @returns a floating point number representing the price */ getConfAsNumberUnchecked() { return Number(this.conf) * 10 ** this.expo; } static fromJson(json) { const jsonPrice = PriceFeed_1.Convert.toPrice(json); return new Price({ conf: jsonPrice.conf, expo: jsonPrice.expo, price: jsonPrice.price, publishTime: jsonPrice.publish_time, }); } toJson() { const jsonPrice = { conf: this.conf, expo: this.expo, price: this.price, publish_time: this.publishTime, }; // this is done to avoid sending undefined values to the server return PriceFeed_1.Convert.priceToJson(jsonPrice); } } exports.Price = Price; /** * Metadata about the price * * Represents metadata of a price feed. */ class PriceFeedMetadata { /** * Attestation time of the price */ attestationTime; /** * Chain of the emitter */ emitterChain; /** * The time that the price service received the price */ priceServiceReceiveTime; /** * Sequence number of the price */ sequenceNumber; /** * Pythnet slot number of the price */ slot; /** * The time that the previous price was published */ prevPublishTime; constructor(metadata) { this.attestationTime = metadata.attestationTime; this.emitterChain = metadata.emitterChain; this.priceServiceReceiveTime = metadata.receiveTime; this.sequenceNumber = metadata.sequenceNumber; this.slot = metadata.slot; this.prevPublishTime = metadata.prevPublishTime; } static fromJson(json) { if (json === undefined) { return undefined; } const jsonFeed = PriceFeed_1.Convert.toPriceFeedMetadata(json); return new PriceFeedMetadata({ attestationTime: jsonFeed.attestation_time, emitterChain: jsonFeed.emitter_chain, receiveTime: jsonFeed.price_service_receive_time, sequenceNumber: jsonFeed.sequence_number, slot: jsonFeed.slot, prevPublishTime: jsonFeed.prev_publish_time, }); } toJson() { const jsonFeed = { attestation_time: this.attestationTime, emitter_chain: this.emitterChain, price_service_receive_time: this.priceServiceReceiveTime, sequence_number: this.sequenceNumber, slot: this.slot, prev_publish_time: this.prevPublishTime, }; // this is done to avoid sending undefined values to the server return PriceFeed_1.Convert.priceFeedMetadataToJson(jsonFeed); } } exports.PriceFeedMetadata = PriceFeedMetadata; /** * Pyth Price Feed * * Represents a current aggregation price from pyth publisher feeds. */ class PriceFeed { /** * Exponentially-weighted moving average Price */ emaPrice; /** * Unique identifier for this price. */ id; /** * Metadata of the price */ metadata; /** * VAA of the price */ vaa; /** * Price */ price; constructor(rawFeed) { this.emaPrice = rawFeed.emaPrice; this.id = rawFeed.id; this.metadata = rawFeed.metadata; this.vaa = rawFeed.vaa; this.price = rawFeed.price; } static fromJson(json) { const jsonFeed = PriceFeed_1.Convert.toPriceFeed(json); return new PriceFeed({ emaPrice: Price.fromJson(jsonFeed.ema_price), id: jsonFeed.id, metadata: PriceFeedMetadata.fromJson(jsonFeed.metadata), vaa: jsonFeed.vaa, price: Price.fromJson(jsonFeed.price), }); } toJson() { const jsonFeed = { ema_price: this.emaPrice.toJson(), id: this.id, metadata: this.metadata?.toJson(), price: this.price.toJson(), }; return PriceFeed_1.Convert.priceFeedToJson(jsonFeed); } /** * Get the price and confidence interval as fixed-point numbers of the form a * 10^e. * This function returns the current best estimate of the price at the time that this `PriceFeed` was * published (`publishTime`). The returned price can be from arbitrarily far in the past; this function * makes no guarantees that the returned price is recent or useful for any particular application. * * Users of this function should check the returned `publishTime` to ensure that the returned price is * sufficiently recent for their application. If you are considering using this function, it may be * safer / easier to use `getPriceNoOlderThan` method. * * @returns a Price that contains the price and confidence interval along with * the exponent for them, and publish time of the price. */ getPriceUnchecked() { return this.price; } /** * Get the exponentially-weighted moving average (EMA) price and confidence interval. * * This function returns the current best estimate of the price at the time that this `PriceFeed` was * published (`publishTime`). The returned price can be from arbitrarily far in the past; this function * makes no guarantees that the returned price is recent or useful for any particular application. * * Users of this function should check the returned `publishTime` to ensure that the returned price is * sufficiently recent for their application. If you are considering using this function, it may be * safer / easier to use `getEmaPriceNoOlderThan` method. * * At the moment, the confidence interval returned by this method is computed in * a somewhat questionable way, so we do not recommend using it for high-value applications. * * @returns a Price that contains the EMA price and confidence interval along with * the exponent for them, and publish time of the price. */ getEmaPriceUnchecked() { return this.emaPrice; } /** * Get the price if it was updated no older than `age` seconds of the current time. * * This function is a sanity-checked version of `getPriceUnchecked` which is useful in * applications that require a sufficiently-recent price. Returns `undefined` if the price * is not recent enough. * * @param age return a price as long as it has been updated within this number of seconds * @returns a Price struct containing the price, confidence interval along with the exponent for * both numbers, and its publish time, or `undefined` if no price update occurred within `age` seconds of the current time. */ getPriceNoOlderThan(age) { const price = this.getPriceUnchecked(); const currentTime = Math.floor(Date.now() / 1000); // This checks the absolute difference as a sanity check // for the cases that the system time is behind or price // feed timestamp happen to be in the future (a bug). if (Math.abs(currentTime - price.publishTime) > age) { return undefined; } return price; } /** * Get the exponentially-weighted moving average (EMA) price if it was updated no older than * `age` seconds of the current time. * * This function is a sanity-checked version of `getEmaPriceUnchecked` which is useful in * applications that require a sufficiently-recent price. Returns `undefined` if the price * is not recent enough. * * At the moment, the confidence interval returned by this method is computed in * a somewhat questionable way, so we do not recommend using it for high-value applications. * * @param age return a price as long as it has been updated within this number of seconds * @returns a Price struct containing the EMA price, confidence interval along with the exponent for * both numbers, and its publish time, or `undefined` if no price update occurred within `age` seconds of the current time. */ getEmaPriceNoOlderThan(age) { const emaPrice = this.getEmaPriceUnchecked(); const currentTime = Math.floor(Date.now() / 1000); // This checks the absolute difference as a sanity check // for the cases that the system time is behind or price // feed timestamp happen to be in the future (a bug). if (Math.abs(currentTime - emaPrice.publishTime) > age) { return undefined; } return emaPrice; } /** * Get the price feed metadata. * * @returns a struct containing the attestation time, emitter chain, and the sequence number. * Returns `undefined` if metadata is currently unavailable. */ getMetadata() { return this.metadata; } /** * Get the price feed vaa. * * @returns vaa in base64. * Returns `undefined` if vaa is unavailable. */ getVAA() { return this.vaa; } } exports.PriceFeed = PriceFeed;