From 1b9d17c7ba187b8ec445e921b3c268d365ce1f69 Mon Sep 17 00:00:00 2001 From: Ali Behjati Date: Wed, 28 Aug 2024 16:10:55 +0200 Subject: [PATCH] feat: add InitPriceFeedIndex method IDL (#80) * feat: add InitPriceFeedIndex method IDL * fix: update tests to use pythnet/pythtest * fix: address review comments * feat: add tests for this instruction and setMaxLatency * refactor: format * fix: remove permissions account from the test as its pda * feat: add account parsing * fix: address lint issues * fix: update oracle version in idl.json --- package-lock.json | 4 +-- package.json | 2 +- src/__tests__/Anchor.test.ts | 30 ++++++++++++++-- src/__tests__/Example.test.ts | 6 ++-- src/__tests__/Mapping.test.ts | 6 ++-- src/__tests__/Price.test.ts | 38 +++++++++++++++++++-- src/__tests__/Product.ETH.test.ts | 6 ++-- src/__tests__/Product.test.ts | 5 +-- src/__tests__/PythNetworkRestClient.test.ts | 15 ++++---- src/anchor/idl.json | 35 +++++++++++++++++-- src/anchor/program.ts | 35 +++++++++++++++++-- src/cluster.ts | 2 +- src/index.ts | 29 +++++++++++----- 13 files changed, 175 insertions(+), 38 deletions(-) diff --git a/package-lock.json b/package-lock.json index d9080fb..6211421 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@pythnetwork/client", - "version": "2.21.1", + "version": "2.22.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@pythnetwork/client", - "version": "2.21.1", + "version": "2.22.0", "license": "Apache-2.0", "dependencies": { "@coral-xyz/anchor": "^0.29.0", diff --git a/package.json b/package.json index e17962b..5af1a4e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@pythnetwork/client", - "version": "2.21.1", + "version": "2.22.0", "description": "Client for consuming Pyth price data", "homepage": "https://pyth.network", "main": "lib/index.js", diff --git a/src/__tests__/Anchor.test.ts b/src/__tests__/Anchor.test.ts index 1f988d0..7ac83bd 100644 --- a/src/__tests__/Anchor.test.ts +++ b/src/__tests__/Anchor.test.ts @@ -1,16 +1,17 @@ import { AnchorProvider, Wallet } from '@coral-xyz/anchor' import { Connection, Keypair, PublicKey } from '@solana/web3.js' import { BN } from 'bn.js' +import { getPythClusterApiUrl } from '../cluster' import { getPythProgramKeyForCluster, pythOracleProgram, pythOracleCoder } from '../index' test('Anchor', (done) => { jest.setTimeout(60000) const provider = new AnchorProvider( - new Connection('https://api.mainnet-beta.solana.com'), + new Connection(getPythClusterApiUrl('pythnet')), new Wallet(new Keypair()), AnchorProvider.defaultOptions(), ) - const pythOracle = pythOracleProgram(getPythProgramKeyForCluster('mainnet-beta'), provider) + const pythOracle = pythOracleProgram(getPythProgramKeyForCluster('pythnet'), provider) pythOracle.methods .initMapping() .accounts({ fundingAccount: PublicKey.unique(), freshMappingAccount: PublicKey.unique() }) @@ -202,5 +203,30 @@ test('Anchor', (done) => { expect(decoded?.data.securityAuthority.equals(new PublicKey(8))).toBeTruthy() }) + pythOracle.methods + .setMaxLatency(1, [0, 0, 0]) + .accounts({ fundingAccount: PublicKey.unique(), priceAccount: PublicKey.unique() }) + .instruction() + .then((instruction) => { + expect(instruction.data).toStrictEqual(Buffer.from([2, 0, 0, 0, 18, 0, 0, 0, 1, 0, 0, 0])) + const decoded = pythOracleCoder().instruction.decode(instruction.data) + expect(decoded?.name).toBe('setMaxLatency') + expect(decoded?.data.maxLatency === 1).toBeTruthy() + }) + + pythOracle.methods + .initPriceFeedIndex() + .accounts({ + fundingAccount: PublicKey.unique(), + priceAccount: PublicKey.unique(), + }) + .instruction() + .then((instruction) => { + expect(instruction.data).toStrictEqual(Buffer.from([2, 0, 0, 0, 19, 0, 0, 0])) + const decoded = pythOracleCoder().instruction.decode(instruction.data) + expect(decoded?.name).toBe('initPriceFeedIndex') + expect(decoded?.data).toStrictEqual({}) + }) + done() }) diff --git a/src/__tests__/Example.test.ts b/src/__tests__/Example.test.ts index ca9803e..b9d1399 100644 --- a/src/__tests__/Example.test.ts +++ b/src/__tests__/Example.test.ts @@ -1,7 +1,7 @@ -import { clusterApiUrl, Connection, PublicKey } from '@solana/web3.js' -import { parseMappingData, parsePriceData, parseProductData } from '../index' +import { Connection, PublicKey } from '@solana/web3.js' +import { getPythClusterApiUrl, parseMappingData, parsePriceData, parseProductData } from '../index' -const SOLANA_CLUSTER_URL = clusterApiUrl('devnet') +const SOLANA_CLUSTER_URL = getPythClusterApiUrl('pythtest-crosschain') const ORACLE_MAPPING_PUBLIC_KEY = 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2' test('Mapping', (done) => { diff --git a/src/__tests__/Mapping.test.ts b/src/__tests__/Mapping.test.ts index eaef299..c4bb3c6 100644 --- a/src/__tests__/Mapping.test.ts +++ b/src/__tests__/Mapping.test.ts @@ -1,9 +1,9 @@ -import { clusterApiUrl, Connection, PublicKey } from '@solana/web3.js' -import { parseMappingData, Magic, Version } from '../index' +import { Connection, PublicKey } from '@solana/web3.js' +import { parseMappingData, Magic, Version, getPythClusterApiUrl } from '../index' test('Mapping', (done) => { jest.setTimeout(60000) - const url = clusterApiUrl('devnet') + const url = getPythClusterApiUrl('pythtest-crosschain') const oraclePublicKey = 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2' const connection = new Connection(url) const publicKey = new PublicKey(oraclePublicKey) diff --git a/src/__tests__/Price.test.ts b/src/__tests__/Price.test.ts index 94cbf16..de03b29 100644 --- a/src/__tests__/Price.test.ts +++ b/src/__tests__/Price.test.ts @@ -1,5 +1,6 @@ -import { clusterApiUrl, Connection, PublicKey } from '@solana/web3.js' +import { Connection, PublicKey } from '@solana/web3.js' import { + getPythClusterApiUrl, Magic, MAX_SLOT_DIFFERENCE, parseMappingData, @@ -11,7 +12,7 @@ import { test('Price', (done) => { jest.setTimeout(60000) - const url = clusterApiUrl('devnet') + const url = getPythClusterApiUrl('pythtest-crosschain') const oraclePublicKey = 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2' const connection = new Connection(url) const publicKey = new PublicKey(oraclePublicKey) @@ -103,6 +104,9 @@ test('Handle price getting stale', (done) => { expect(price.magic).toBe(Magic) expect(price.version).toBe(Version) expect(price.status).toBe(PriceStatus.Trading) + expect(price.flags.accumulatorV2).toBe(false); + expect(price.flags.messageBufferCleared).toBe(false); + expect(price.feedIndex).toBe(0) expect(parsePriceData(data, price.aggregate.publishSlot + MAX_SLOT_DIFFERENCE).status).toBe(PriceStatus.Trading) @@ -128,3 +132,33 @@ test('Handle ignored quote', (done) => { done() }) + +test('Handle flags', (done) => { + jest.setTimeout(60000) + + // This data is the BTC price account on Pythnet at 27 Aug 2024 while some flags are set + const b64_data = + '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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa/TMEwuo74QSAAAAAAAAAOxOpnA8+9UCAAAAAAAAAADaZAAAAAAAAAAAAAAAAAAA' + + const data = Buffer.from(b64_data, 'base64') + const price = parsePriceData(data) + + expect(price.flags.accumulatorV2).toBe(true); + expect(price.flags.messageBufferCleared).toBe(true); + + done() +}) + +test('Handle priceFeedIndex', (done) => { + jest.setTimeout(60000) + + // This data is the same as above, except that the feed index is manually modified to be a5 + const b64_data = + '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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAa/TMEwuo74QSAAAAAAAAAOxOpnA8+9UCAAAAAAAAAADaZAAAAAAAAAAAAAAAAAAA' + + const data = Buffer.from(b64_data, 'base64') + const price = parsePriceData(data) + + expect(price.feedIndex).toBe(165) + done() +}) diff --git a/src/__tests__/Product.ETH.test.ts b/src/__tests__/Product.ETH.test.ts index a3af53f..7bc8629 100644 --- a/src/__tests__/Product.ETH.test.ts +++ b/src/__tests__/Product.ETH.test.ts @@ -1,9 +1,9 @@ -import { clusterApiUrl, Connection, PublicKey } from '@solana/web3.js' -import { Magic, parseProductData, Version } from '../index' +import { Connection, PublicKey } from '@solana/web3.js' +import { getPythClusterApiUrl, Magic, parseProductData, Version } from '../index' test('Product', (done) => { jest.setTimeout(60000) - const url = clusterApiUrl('devnet') + const url = getPythClusterApiUrl('pythtest-crosschain') const ethProductKey = '2ciUuGZiee5macAMeQ7bHGTJtwcYTgnt6jdmQnnKZrfu' const connection = new Connection(url) const publicKey = new PublicKey(ethProductKey) diff --git a/src/__tests__/Product.test.ts b/src/__tests__/Product.test.ts index 0354055..9d27268 100644 --- a/src/__tests__/Product.test.ts +++ b/src/__tests__/Product.test.ts @@ -1,9 +1,10 @@ -import { clusterApiUrl, Connection, PublicKey } from '@solana/web3.js' +import { Connection, PublicKey } from '@solana/web3.js' +import { getPythClusterApiUrl } from '../cluster' import { parseMappingData, parseProductData, Magic, Version } from '../index' test('Product', (done) => { jest.setTimeout(60000) - const url = clusterApiUrl('devnet') + const url = getPythClusterApiUrl('pythtest-crosschain') const oraclePublicKey = 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2' const connection = new Connection(url) const publicKey = new PublicKey(oraclePublicKey) diff --git a/src/__tests__/PythNetworkRestClient.test.ts b/src/__tests__/PythNetworkRestClient.test.ts index a524e79..abd1240 100644 --- a/src/__tests__/PythNetworkRestClient.test.ts +++ b/src/__tests__/PythNetworkRestClient.test.ts @@ -1,11 +1,12 @@ -import { clusterApiUrl, Connection, PublicKey, SystemProgram } from '@solana/web3.js' +import { Connection, PublicKey, SystemProgram } from '@solana/web3.js' import { getPythProgramKeyForCluster, parseProductData, PythHttpClient } from '..' +import { getPythClusterApiUrl } from '../cluster' test('PythHttpClientCall: getData', (done) => { - jest.setTimeout(20000) + jest.setTimeout(60000) try { - const programKey = getPythProgramKeyForCluster('testnet') - const currentConnection = new Connection(clusterApiUrl('testnet')) + const programKey = getPythProgramKeyForCluster('pythtest-conformance') + const currentConnection = new Connection(getPythClusterApiUrl('pythtest-conformance')) const pyth_client = new PythHttpClient(currentConnection, programKey) pyth_client.getData().then( (result) => { @@ -30,7 +31,7 @@ test('PythHttpClientCall: getAssetPricesFromAccounts for one account', (done) => const solUSDKey = new PublicKey('7VJsBtJzgTftYzEeooSDYyjKXvYRWJHdwvbwfBvTg9K') try { const programKey = getPythProgramKeyForCluster('testnet') - const currentConnection = new Connection(clusterApiUrl('testnet')) + const currentConnection = new Connection(getPythClusterApiUrl('pythtest-conformance')) const pyth_client = new PythHttpClient(currentConnection, programKey) pyth_client .getAssetPricesFromAccounts([solUSDKey]) @@ -66,7 +67,7 @@ test('PythHttpClientCall: getAssetPricesFromAccounts for multiple accounts', (do try { const programKey = getPythProgramKeyForCluster('testnet') - const currentConnection = new Connection(clusterApiUrl('testnet')) + const currentConnection = new Connection(getPythClusterApiUrl('pythtest-conformance')) const pyth_client = new PythHttpClient(currentConnection, programKey) pyth_client .getAssetPricesFromAccounts([solUSDKey, bonkUSDKey, usdcUSDKey]) @@ -106,7 +107,7 @@ test('PythHttpClientCall: getAssetPricesFromAccounts should throw for invalid ac try { const programKey = getPythProgramKeyForCluster('testnet') - const currentConnection = new Connection(clusterApiUrl('testnet')) + const currentConnection = new Connection(getPythClusterApiUrl('pythtest-conformance')) const pyth_client = new PythHttpClient(currentConnection, programKey) pyth_client .getAssetPricesFromAccounts([solUSDKey, systemProgram, usdcUSDKey]) diff --git a/src/anchor/idl.json b/src/anchor/idl.json index 927802f..d4b158c 100644 --- a/src/anchor/idl.json +++ b/src/anchor/idl.json @@ -1,5 +1,5 @@ { - "version": "2.20.0", + "version": "2.33.0", "name": "pyth_oracle", "instructions": [ { @@ -171,7 +171,7 @@ }, { "name": "permissionsAccount", - "isMut": false, + "isMut": true, "isSigner": false, "pda": { "seeds": [ @@ -640,6 +640,37 @@ } } ] + }, + { + "name": "initPriceFeedIndex", + "discriminant": { "value": [2, 0, 0, 0, 19, 0, 0, 0] }, + "accounts": [ + { + "name": "fundingAccount", + "isMut": true, + "isSigner": true + }, + { + "name": "priceAccount", + "isMut": true, + "isSigner": false + }, + { + "name": "permissionsAccount", + "isMut": true, + "isSigner": false, + "pda": { + "seeds": [ + { + "kind": "const", + "type": "string", + "value": "permissions" + } + ] + } + } + ], + "args": [] } ], "types": [ diff --git a/src/anchor/program.ts b/src/anchor/program.ts index a61705e..d3c9a7c 100644 --- a/src/anchor/program.ts +++ b/src/anchor/program.ts @@ -19,7 +19,7 @@ export function pythOracleCoder(): PythOracleCoder { export { default as pythIdl } from './idl.json' export type PythOracle = { - version: '2.20.0' + version: '2.33.0' name: 'pyth_oracle' instructions: [ { @@ -191,7 +191,7 @@ export type PythOracle = { }, { name: 'permissionsAccount' - isMut: false + isMut: true isSigner: false pda: { seeds: [ @@ -661,6 +661,37 @@ export type PythOracle = { }, ] }, + { + name: 'initPriceFeedIndex' + discriminant: { value: [2, 0, 0, 0, 19, 0, 0, 0] } + accounts: [ + { + name: 'fundingAccount' + isMut: true + isSigner: true + }, + { + name: 'priceAccount' + isMut: true + isSigner: false + }, + { + name: 'permissionsAccount' + isMut: true + isSigner: false + pda: { + seeds: [ + { + kind: 'const' + type: 'string' + value: 'permissions' + }, + ] + } + }, + ] + args: [] + }, ] types: [ { diff --git a/src/cluster.ts b/src/cluster.ts index fd09c0d..cefdf19 100644 --- a/src/cluster.ts +++ b/src/cluster.ts @@ -32,7 +32,7 @@ export function getPythClusterApiUrl(cluster: PythCluster): string { if (cluster === 'pythtest-conformance' || cluster === 'pythtest-crosschain') { return 'https://api.pythtest.pyth.network' } else if (cluster === 'pythnet') { - return 'https://pythnet.rpcpool.com' + return 'https://api2.pythnet.pyth.network' } else if (cluster === 'localnet') { return 'http://localhost:8899' } else { diff --git a/src/index.ts b/src/index.ts index 5cef564..a57be35 100644 --- a/src/index.ts +++ b/src/index.ts @@ -41,6 +41,11 @@ export enum AccountType { Permission, } +export type Flags = { + accumulatorV2: boolean, + messageBufferCleared: boolean, +} + const empty32Buffer = Buffer.alloc(32) const PKorNull = (data: Buffer) => (data.equals(empty32Buffer) ? null : new PublicKey(data)) @@ -105,8 +110,8 @@ export interface PriceData extends Base { minPublishers: number messageSent: number maxLatency: number - drv3: number - drv4: number + flags: Flags, + feedIndex: number productAccountKey: PublicKey nextPriceAccountKey: PublicKey | null previousSlot: bigint @@ -290,10 +295,18 @@ export const parsePriceData = (data: Buffer, currentSlot?: number): PriceData => const messageSent = data.readUInt8(105) // configurable max latency in slots between send and receive const maxLatency = data.readUInt8(106) - // space for future derived values - const drv3 = data.readInt8(107) - // space for future derived values - const drv4 = data.readInt32LE(108) + // Various flags (used for operations) + const flagBits = data.readInt8(107) + + /* tslint:disable:no-bitwise */ + const flags = { + accumulatorV2: (flagBits & (1<<0)) !== 0, + messageBufferCleared: (flagBits & (1<<1)) !== 0, + } + /* tslint:enable:no-bitwise */ + + // Globally immutable unique price feed index used for publishing. + const feedIndex = data.readInt32LE(108) // product id / reference account const productAccountKey = new PublicKey(data.slice(112, 144)) // next price account in list @@ -355,8 +368,8 @@ export const parsePriceData = (data: Buffer, currentSlot?: number): PriceData => minPublishers, messageSent, maxLatency, - drv3, - drv4, + flags, + feedIndex, productAccountKey, nextPriceAccountKey, previousSlot,