diff --git a/src/PythConnection.ts b/src/PythConnection.ts index eafe6ce..94c1de0 100644 --- a/src/PythConnection.ts +++ b/src/PythConnection.ts @@ -30,7 +30,8 @@ export class PythConnection { connection: Connection pythProgramKey: PublicKey commitment: Commitment - feedIds?: PublicKey[] + feedIds: PublicKey[] + productIds: PublicKey[] productAccountKeyToProduct: Record> = {} priceAccountKeyToProductAccountKey: Record = {} @@ -109,53 +110,96 @@ export class PythConnection { connection: Connection, pythProgramKey: PublicKey, commitment: Commitment = 'finalized', - feedIds?: PublicKey[], + feedIds: PublicKey[], + productIds: PublicKey[], ) { this.connection = connection this.pythProgramKey = pythProgramKey this.commitment = commitment this.feedIds = feedIds + this.productIds = productIds } + // public async start() { + // const accSlotProm = await Promise.all([ + // this.connection.getProgramAccounts(this.pythProgramKey, this.commitment), + // this.connection.getSlot(this.commitment), + // ]) + // let accounts = accSlotProm[0] + // const currentSlot = accSlotProm[1] + // // Handle all accounts once since we need to handle product accounts + // // at least once + // for (const account of accounts) { + // this.handleAccount(account.pubkey, account.account, true, currentSlot) + // } + + // if (this.feedIds) { + // // Filter down to only the feeds we want + // const rawIDs = this.feedIds.map((feed) => feed.toString()) + // accounts = accounts.filter((feed) => rawIDs.includes(feed.pubkey.toString())) + + // console.log('ACCOUNTS', accounts); + + + // for (const account of accounts) { + // this.connection.onAccountChange( + // account.pubkey, + + // (accountInfo, context) => { + // this.handleAccount(account.pubkey, accountInfo, false, context.slot) + // }, + // this.commitment, + // ) + // } + // } else { + // this.connection.onProgramAccountChange( + // this.pythProgramKey, + // (keyedAccountInfo, context) => { + // this.handleAccount(keyedAccountInfo.accountId, keyedAccountInfo.accountInfo, false, context.slot) + // }, + // this.commitment, + // ) + // } + // } + /** Start receiving price updates. Once this method is called, any registered callbacks will be invoked * each time a Pyth price account is updated. */ public async start() { const accSlotProm = await Promise.all([ - this.connection.getProgramAccounts(this.pythProgramKey, this.commitment), + this.connection.getMultipleAccountsInfo([...this.feedIds, ...this.productIds], this.commitment), this.connection.getSlot(this.commitment), ]) + let accounts = accSlotProm[0] const currentSlot = accSlotProm[1] + + // Register products accounts + this.productIds.forEach((productId, i) => { + const acc = accounts[i + this.feedIds.length]; + + if (acc === null) return; + + this.handleAccount(productId, acc, true, currentSlot) + }); + // Handle all accounts once since we need to handle product accounts // at least once - for (const account of accounts) { - this.handleAccount(account.pubkey, account.account, true, currentSlot) - } + this.feedIds.forEach((accountId, i) => { + const acc = accounts[i]; - if (this.feedIds) { - // Filter down to only the feeds we want - const rawIDs = this.feedIds.map((feed) => feed.toString()) - accounts = accounts.filter((feed) => rawIDs.includes(feed.pubkey.toString())) - for (const account of accounts) { - this.connection.onAccountChange( - account.pubkey, - - (accountInfo, context) => { - this.handleAccount(account.pubkey, accountInfo, false, context.slot) - }, - this.commitment, - ) - } - } else { - this.connection.onProgramAccountChange( - this.pythProgramKey, - (keyedAccountInfo, context) => { - this.handleAccount(keyedAccountInfo.accountId, keyedAccountInfo.accountInfo, false, context.slot) + if (acc === null) return; + + this.handleAccount(accountId, acc, true, currentSlot) + + this.connection.onAccountChange( + accountId, + (accountInfo, context) => { + this.handleAccount(accountId, accountInfo, false, context.slot) }, this.commitment, ) - } + }); } /** Register callback to receive price updates. */ diff --git a/src/example_ws_single_feed.ts b/src/example_ws_single_feed.ts index 75c089d..79d4cf0 100644 --- a/src/example_ws_single_feed.ts +++ b/src/example_ws_single_feed.ts @@ -9,7 +9,7 @@ const pythPublicKey = getPythProgramKeyForCluster(PYTHNET_CLUSTER_NAME) // This example shows Crypto.SOL/USD const feeds = [new PublicKey('H6ARHf6YXhGYeQfUzQNGk6rDNnLBQKrenN712K4AQJEG')] -const pythConnection = new PythConnection(connection, pythPublicKey, 'confirmed', feeds) +const pythConnection = new PythConnection(connection, pythPublicKey, 'confirmed', feeds, []) pythConnection.onPriceChangeVerbose((productAccount, priceAccount) => { // The arguments to the callback include solana account information / the update slot if you need it. const product = productAccount.accountInfo.data.product diff --git a/src/example_ws_usage.ts b/src/example_ws_usage.ts index 30156e2..2fcbaaa 100644 --- a/src/example_ws_usage.ts +++ b/src/example_ws_usage.ts @@ -5,7 +5,7 @@ const PYTHNET_CLUSTER_NAME: PythCluster = 'pythnet' const connection = new Connection(getPythClusterApiUrl(PYTHNET_CLUSTER_NAME)) const pythPublicKey = getPythProgramKeyForCluster(PYTHNET_CLUSTER_NAME) -const pythConnection = new PythConnection(connection, pythPublicKey) +const pythConnection = new PythConnection(connection, pythPublicKey, "finalized", [], []) pythConnection.onPriceChangeVerbose((productAccount, priceAccount) => { // The arguments to the callback include solana account information / the update slot if you need it. const product = productAccount.accountInfo.data.product