UNPKG

@pythnetwork/price-service-sdk

Version:
192 lines (191 loc) 6.17 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); function _export(target, all) { for(var name in all)Object.defineProperty(target, name, { enumerable: true, get: Object.getOwnPropertyDescriptor(all, name).get }); } _export(exports, { get isAccumulatorUpdateData () { return isAccumulatorUpdateData; }, get parseAccumulatorUpdateData () { return parseAccumulatorUpdateData; }, get parsePriceFeedMessage () { return parsePriceFeedMessage; }, get parseTwapMessage () { return parseTwapMessage; }, get sliceAccumulatorUpdateData () { return sliceAccumulatorUpdateData; } }); const _bn = /*#__PURE__*/ _interop_require_default(require("bn.js")); function _interop_require_default(obj) { return obj && obj.__esModule ? obj : { default: obj }; } const ACCUMULATOR_MAGIC = "504e4155"; const MAJOR_VERSION = 1; const MINOR_VERSION = 0; const KECCAK160_HASH_SIZE = 20; const PRICE_FEED_MESSAGE_VARIANT = 0; const TWAP_MESSAGE_VARIANT = 1; function isAccumulatorUpdateData(updateBytes) { return updateBytes.toString("hex").startsWith(ACCUMULATOR_MAGIC) && updateBytes[4] === MAJOR_VERSION && updateBytes[5] === MINOR_VERSION; } function parsePriceFeedMessage(message) { let cursor = 0; const variant = message.readUInt8(cursor); if (variant !== PRICE_FEED_MESSAGE_VARIANT) { throw new Error("Not a price feed message"); } cursor += 1; const feedId = message.subarray(cursor, cursor + 32); cursor += 32; const price = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const confidence = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const exponent = message.readInt32BE(cursor); cursor += 4; const publishTime = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const prevPublishTime = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const emaPrice = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const emaConf = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; return { feedId, price, confidence, exponent, publishTime, prevPublishTime, emaPrice, emaConf }; } function parseTwapMessage(message) { let cursor = 0; const variant = message.readUInt8(cursor); if (variant !== TWAP_MESSAGE_VARIANT) { throw new Error("Not a twap message"); } cursor += 1; const feedId = message.subarray(cursor, cursor + 32); cursor += 32; const cumulativePrice = new _bn.default(message.subarray(cursor, cursor + 16), "be"); cursor += 16; const cumulativeConf = new _bn.default(message.subarray(cursor, cursor + 16), "be"); cursor += 16; const numDownSlots = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const exponent = message.readInt32BE(cursor); cursor += 4; const publishTime = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const prevPublishTime = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; const publishSlot = new _bn.default(message.subarray(cursor, cursor + 8), "be"); cursor += 8; return { feedId, cumulativePrice, cumulativeConf, numDownSlots, exponent, publishTime, prevPublishTime, publishSlot }; } function sliceAccumulatorUpdateData(data, start, end) { if (!isAccumulatorUpdateData(data)) { throw new Error("Invalid accumulator message"); } let cursor = 6; const trailingPayloadSize = data.readUint8(cursor); cursor += 1 + trailingPayloadSize; // const proofType = data.readUint8(cursor); cursor += 1; const vaaSize = data.readUint16BE(cursor); cursor += 2; cursor += vaaSize; const endOfVaa = cursor; const updates = []; const numUpdates = data.readUInt8(cursor); cursor += 1; for(let i = 0; i < numUpdates; i++){ const updateStart = cursor; const messageSize = data.readUint16BE(cursor); cursor += 2; cursor += messageSize; const numProofs = data.readUInt8(cursor); cursor += 1; cursor += KECCAK160_HASH_SIZE * numProofs; updates.push(data.subarray(updateStart, cursor)); } if (cursor !== data.length) { throw new Error("Didn't reach the end of the message"); } const sliceUpdates = updates.slice(start, end); return Buffer.concat([ data.subarray(0, endOfVaa), Buffer.from([ sliceUpdates.length ]), ...updates.slice(start, end) ]); } function parseAccumulatorUpdateData(data) { if (!isAccumulatorUpdateData(data)) { throw new Error("Invalid accumulator message"); } let cursor = 6; const trailingPayloadSize = data.readUint8(cursor); cursor += 1 + trailingPayloadSize; // const proofType = data.readUint8(cursor); cursor += 1; const vaaSize = data.readUint16BE(cursor); cursor += 2; const vaa = data.subarray(cursor, cursor + vaaSize); cursor += vaaSize; const numUpdates = data.readUInt8(cursor); const updates = []; cursor += 1; for(let i = 0; i < numUpdates; i++){ const messageSize = data.readUint16BE(cursor); cursor += 2; const message = data.subarray(cursor, cursor + messageSize); cursor += messageSize; const numProofs = data.readUInt8(cursor); cursor += 1; const proof = []; for(let j = 0; j < numProofs; j++){ proof.push([ ...data.subarray(cursor, cursor + KECCAK160_HASH_SIZE) ]); cursor += KECCAK160_HASH_SIZE; } updates.push({ message, proof }); } if (cursor !== data.length) { throw new Error("Didn't reach the end of the message"); } return { vaa, updates }; }