@pythnetwork/pyth-solana-receiver
Version:
Pyth solana receiver SDK
394 lines • 24.9 kB
TypeScript
import { AnchorProvider, IdlAccounts, Program } from "@coral-xyz/anchor";
import { AddressLookupTableAccount, Connection, Signer, Transaction, VersionedTransaction } from "@solana/web3.js";
import { PythSolanaReceiver as PythSolanaReceiverProgram } from "./idl/pyth_solana_receiver";
import { WormholeCoreBridgeSolana } from "./idl/wormhole_core_bridge_solana";
import { PublicKey } from "@solana/web3.js";
import { Wallet } from "@coral-xyz/anchor";
import { TransactionBuilder, InstructionWithEphemeralSigners, PriorityFeeConfig } from "@pythnetwork/solana-utils";
import { PythPushOracle } from "./idl/pyth_push_oracle";
export type PriceUpdateAccount = IdlAccounts<PythSolanaReceiverProgram>["priceUpdateV2"];
export type TwapUpdateAccount = IdlAccounts<PythSolanaReceiverProgram>["twapUpdate"];
/**
* Configuration for the PythTransactionBuilder
* @property closeUpdateAccounts (default: true) if true, the builder will add instructions to close the price update accounts and the encoded vaa accounts to recover the rent
*/
export type PythTransactionBuilderConfig = {
closeUpdateAccounts?: boolean;
};
/**
* A stable treasury ID. This ID's corresponding treasury address
* can be cached in an account lookup table in order to reduce the overall txn size.
*/
export declare const DEFAULT_TREASURY_ID = 0;
/**
* A builder class to build transactions that:
* - Post price updates (fully or partially verified) or update price feed accounts
* - Consume price updates in a consumer program
* - (Optionally) Close price update and encoded vaa accounts to recover the rent (`closeUpdateAccounts` in `PythTransactionBuilderConfig`)
*
* This class provides methods for working with both price update accounts and price feed accounts.
* Price update accounts are ephemeral accounts containing a single price update, whereas price feed accounts are long-lived
* accounts that always hold price data for a specific feed id. Price feed accounts can be updated to advance the current price.
* Applications should choose which type of account to work with based on their needs. In general, applications that
* want the price at a specific time (e.g., to settle a trade) should use price update accounts, while applications that want
* any recent price should use price feed accounts.
*
* @example
* ```typescript
*
* // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
* const priceUpdateData = await priceServiceConnection.getLatestVaas([
* SOL_PRICE_FEED_ID,
* ETH_PRICE_FEED_ID,
* ]);
*
* const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
* await transactionBuilder.addPostPriceUpdates(priceUpdateData);
* console.log("The SOL/USD price update will get posted to:", transactionBuilder.getPriceUpdateAccount(SOL_PRICE_FEED_ID).toBase58())
* await transactionBuilder.addPriceConsumerInstructions(...)
*
* await pythSolanaReceiver.provider.sendAll(await transactionBuilder.buildVersionedTransactions({computeUnitPriceMicroLamports:100000, tightComputeBudget: true}))
* ```
*/
export declare class PythTransactionBuilder extends TransactionBuilder {
readonly pythSolanaReceiver: PythSolanaReceiver;
readonly closeInstructions: InstructionWithEphemeralSigners[];
readonly priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>;
readonly priceFeedIdToTwapUpdateAccount: Record<string, PublicKey>;
readonly closeUpdateAccounts: boolean;
constructor(pythSolanaReceiver: PythSolanaReceiver, config: PythTransactionBuilderConfig, addressLookupTable?: AddressLookupTableAccount);
/**
* Add instructions to post price updates to the builder.
* Use this function to post fully verified price updates from the present or from the past for your program to consume.
*
* @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
*
* @example
* ```typescript
* // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
* const priceUpdateData = await priceServiceConnection.getLatestVaas([
* SOL_PRICE_FEED_ID,
* ETH_PRICE_FEED_ID,
* ]);
*
* const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
* await transactionBuilder.addPostPriceUpdates(priceUpdateData);
* console.log("The SOL/USD price update will get posted to:", transactionBuilder.getPriceUpdateAccount(SOL_PRICE_FEED_ID).toBase58())
* await transactionBuilder.addPriceConsumerInstructions(...)
* ```
*/
addPostPriceUpdates(priceUpdateDataArray: string[]): Promise<void>;
/**
* Add instructions to post partially verified price updates to the builder.
* Use this function to post partially verified price updates from the present or from the past for your program to consume.
*
* @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
*
* Partially verified price updates are price updates where not all the guardian signatures have been verified. By default this methods checks `DEFAULT_REDUCED_GUARDIAN_SET_SIZE` signatures when posting the VAA.
* If you are a on-chain program developer, make sure you understand the risks of consuming partially verified price updates here: {@link https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/solana/pyth_solana_receiver_sdk/src/price_update.rs}.
*
* @example
* ```typescript
* // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
* const priceUpdateData = await priceServiceConnection.getLatestVaas([
* SOL_PRICE_FEED_ID,
* ETH_PRICE_FEED_ID,
* ]);
*
* const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
* await transactionBuilder.addPostPartiallyVerifiedPriceUpdates(priceUpdateData);
* console.log("The SOL/USD price update will get posted to:", transactionBuilder.getPriceUpdateAccount(SOL_PRICE_FEED_ID).toBase58())
* await transactionBuilder.addPriceConsumerInstructions(...)
* ...
* ```
*/
addPostPartiallyVerifiedPriceUpdates(priceUpdateDataArray: string[]): Promise<void>;
/**
* Add instructions to post TWAP updates to the builder.
* Use this function to post fully verified TWAP updates from the present or from the past for your program to consume.
*
* @param twapUpdateDataArray the output of the `@pythnetwork/hermes-client`'s `getLatestTwaps`. This is an array of verifiable price updates.
*
* @example
* ```typescript
* // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
* const twapUpdateData = await hermesClient.getLatestTwaps([
* SOL_PRICE_FEED_ID,
* ETH_PRICE_FEED_ID,
* ]);
*
* const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
* await transactionBuilder.addPostTwapUpdates(priceUpdateData);
* console.log("The SOL/USD price update will get posted to:", transactionBuilder.getTwapUpdateAccount(SOL_PRICE_FEED_ID).toBase58())
* await transactionBuilder.addTwapConsumerInstructions(...)
* ```
*/
addPostTwapUpdates(twapUpdateDataArray: string[]): Promise<void>;
/**
* Add instructions to update price feed accounts to the builder.
* Price feed accounts are fixed accounts per price feed id that can only be updated with a more recent price.
*
* @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
* @param shardId the shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
*
* @example
* ```typescript
* // Get the price feed ids from https://pyth.network/developers/price-feed-ids#pyth-evm-stable
* const priceUpdateData = await priceServiceConnection.getLatestVaas([
* SOL_PRICE_FEED_ID,
* ETH_PRICE_FEED_ID,
* ]);
*
* const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({});
* await transactionBuilder.addUpdatePriceFeed(priceUpdateData);
* await transactionBuilder.addPriceConsumerInstructions(...)
* ...
* ```
*/
addUpdatePriceFeed(priceUpdateDataArray: string[], shardId: number): Promise<void>;
/**
* Add instructions that consume price updates to the builder.
*
* @param getInstructions a function that given a mapping of price feed IDs to price update accounts, generates a series of instructions. Price updates get posted to ephemeral accounts and this function allows the user to indicate which accounts in their instruction need to be "replaced" with each price update account.
* If multiple price updates for the same price feed ID are posted with the same builder, the account corresponding to the last update to get posted will be used.
*
* @example
* ```typescript
* ...
* await transactionBuilder.addPostPriceUpdates(priceUpdateData);
* await transactionBuilder.addPriceConsumerInstructions(
* async (
* getPriceUpdateAccount: ( priceFeedId: string) => PublicKey
* ): Promise<InstructionWithEphemeralSigners[]> => {
* return [
* {
* instruction: await myFirstPythApp.methods
* .consume()
* .accounts({
* solPriceUpdate: getPriceUpdateAccount(SOL_PRICE_FEED_ID),
* ethPriceUpdate: getPriceUpdateAccount(ETH_PRICE_FEED_ID),
* })
* .instruction(),
* signers: [],
* },
* ];
* }
* );
* ```
*/
addPriceConsumerInstructions(getInstructions: (getPriceUpdateAccount: (priceFeedId: string) => PublicKey) => Promise<InstructionWithEphemeralSigners[]>): Promise<void>;
/**
* Add instructions that consume TWAP updates to the builder.
*
* @param getInstructions a function that given a mapping of price feed IDs to TWAP update accounts, generates a series of instructions. TWAP updates get posted to ephemeral accounts and this function allows the user to indicate which accounts in their instruction need to be "replaced" with each price update account.
* If multiple TWAP updates for the same price feed ID are posted with the same builder, the account corresponding to the last update to get posted will be used.
*
* @example
* ```typescript
* ...
* await transactionBuilder.addPostTwapUpdates(twapUpdateData);
* await transactionBuilder.addTwapConsumerInstructions(
* async (
* getTwapUpdateAccount: ( priceFeedId: string) => PublicKey
* ): Promise<InstructionWithEphemeralSigners[]> => {
* return [
* {
* instruction: await myFirstPythApp.methods
* .consume()
* .accounts({
* solTwapUpdate: getTwapUpdateAccount(SOL_PRICE_FEED_ID),
* ethTwapUpdate: getTwapUpdateAccount(ETH_PRICE_FEED_ID),
* })
* .instruction(),
* signers: [],
* },
* ];
* }
* );
* ```
*/
addTwapConsumerInstructions(getInstructions: (getTwapUpdateAccount: (priceFeedId: string) => PublicKey) => Promise<InstructionWithEphemeralSigners[]>): Promise<void>;
/** Add instructions to close encoded VAA accounts from previous actions.
* If you have previously used the PythTransactionBuilder with closeUpdateAccounts set to false or if you posted encoded VAAs but the transaction to close them did not land on-chain, your wallet might own many encoded VAA accounts.
* The rent cost for these accounts is 0.008 SOL per encoded VAA account. You can recover this rent calling this function when building a set of transactions.
*/
addClosePreviousEncodedVaasInstructions(maxInstructions?: number): Promise<void>;
/**
* Returns all the added instructions batched into versioned transactions, plus for each transaction the ephemeral signers that need to sign it
*/
buildVersionedTransactions(args: PriorityFeeConfig): Promise<{
tx: VersionedTransaction;
signers: Signer[];
}[]>;
/**
* Returns all the added instructions batched into transactions, plus for each transaction the ephemeral signers that need to sign it
*/
buildLegacyTransactions(args: PriorityFeeConfig): {
tx: Transaction;
signers: Signer[];
}[];
/**
* This method is used to retrieve the address of the price update account where the price update for a given price feed ID will be posted.
* If multiple price updates for the same price feed ID will be posted with the same builder, the address of the account corresponding to the last update to get posted will be returned.
* */
getPriceUpdateAccount(priceFeedId: string): PublicKey;
/**
* This method is used to retrieve the address of the TWAP update account where the TWAP update for a given price feed ID will be posted.
* If multiple updates for the same price feed ID will be posted with the same builder, the address of the account corresponding to the last update to get posted will be returned.
* */
getTwapUpdateAccount(priceFeedId: string): PublicKey;
}
/**
* A class to interact with the Pyth Solana Receiver program.
*
* This class provides helpful methods to build instructions to interact with the Pyth Solana Receiver program:
* - Post price updates (fully or partially verified)
* - Close price update and encoded vaa accounts to recover rent
*/
export declare class PythSolanaReceiver {
readonly connection: Connection;
readonly wallet: Wallet;
readonly provider: AnchorProvider;
readonly receiver: Program<PythSolanaReceiverProgram>;
readonly wormhole: Program<WormholeCoreBridgeSolana>;
readonly pushOracle: Program<PythPushOracle>;
readonly treasuryId?: number;
constructor({ connection, wallet, wormholeProgramId, receiverProgramId, pushOracleProgramId, treasuryId, }: {
connection: Connection;
wallet: Wallet;
wormholeProgramId?: PublicKey;
receiverProgramId?: PublicKey;
pushOracleProgramId?: PublicKey;
treasuryId?: number;
});
/**
* Get a new transaction builder to build transactions that interact with the Pyth Solana Receiver program and consume price updates
*/
newTransactionBuilder(config: PythTransactionBuilderConfig, addressLookupAccount?: AddressLookupTableAccount): PythTransactionBuilder;
/**
* Build a series of helper instructions that post price updates to the Pyth Solana Receiver program and another series to close the price update accounts.
*
* This function uses partially verified price updates. Partially verified price updates are price updates where not all the guardian signatures have been verified. By default this methods checks `DEFAULT_REDUCED_GUARDIAN_SET_SIZE` signatures when posting the VAA.
* If you are a on-chain program developer, make sure you understand the risks of consuming partially verified price updates here: {@link https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/solana/pyth_solana_receiver_sdk/src/price_update.rs}.
*
* @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
* @returns `postInstructions`: the instructions to post the price updates, these should be called before consuming the price updates
* @returns `priceFeedIdToPriceUpdateAccount`: this is a map of price feed IDs to Solana address. Given a price feed ID, you can use this map to find the account where `postInstructions` will post the price update.
* @returns `closeInstructions`: the instructions to close the price update accounts, these should be called after consuming the price updates
*/
buildPostPriceUpdateAtomicInstructions(priceUpdateDataArray: string[]): Promise<{
postInstructions: InstructionWithEphemeralSigners[];
priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>;
closeInstructions: InstructionWithEphemeralSigners[];
}>;
/**
* Build a series of helper instructions that post price updates to the Pyth Solana Receiver program and another series to close the encoded vaa accounts and the price update accounts.
*
* @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
* @returns `postInstructions`: the instructions to post the price updates, these should be called before consuming the price updates
* @returns `priceFeedIdToPriceUpdateAccount`: this is a map of price feed IDs to Solana address. Given a price feed ID, you can use this map to find the account where `postInstructions` will post the price update.
* @returns `closeInstructions`: the instructions to close the price update accounts, these should be called after consuming the price updates
*/
buildPostPriceUpdateInstructions(priceUpdateDataArray: string[]): Promise<{
postInstructions: InstructionWithEphemeralSigners[];
priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>;
closeInstructions: InstructionWithEphemeralSigners[];
}>;
/**
* Build a series of helper instructions that post TWAP updates to the Pyth Solana Receiver program and another series to close the encoded vaa accounts and the TWAP update accounts.
*
* @param twapUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestTwaps`. This is an array of verifiable price updates.
* @returns `postInstructions`: the instructions to post the TWAP updates, these should be called before consuming the price updates
* @returns `priceFeedIdToTwapUpdateAccount`: this is a map of price feed IDs to Solana address. Given a price feed ID, you can use this map to find the account where `postInstructions` will post the TWAP update.
* @returns `closeInstructions`: the instructions to close the TWAP update accounts, these should be called after consuming the TWAP updates
*/
buildPostTwapUpdateInstructions(twapUpdateDataArray: string[]): Promise<{
postInstructions: InstructionWithEphemeralSigners[];
priceFeedIdToTwapUpdateAccount: Record<string, PublicKey>;
closeInstructions: InstructionWithEphemeralSigners[];
}>;
/**
* Build a series of helper instructions that update one or many price feed accounts and another series to close the encoded vaa accounts used to update the price feed accounts.
*
* @param priceUpdateDataArray the output of the `@pythnetwork/price-service-client`'s `PriceServiceConnection.getLatestVaas`. This is an array of verifiable price updates.
* @param shardId the shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
* @returns `postInstructions`: the instructions to update the price feed accounts. If the price feed accounts don't contain a recent update, these should be called before consuming the price updates.
* @returns `priceFeedIdToPriceUpdateAccount`: this is a map of price feed IDs to Solana address. Given a price feed ID, you can use this map to find the account where `postInstructions` will post the price update. Note that since price feed accounts are PDAs, the address of the account can also be found with `getPriceFeedAccountAddress`.
* @returns `closeInstructions`: the instructions to close the encoded VAA accounts that were used to update the price feed accounts.
*/
buildUpdatePriceFeedInstructions(priceUpdateDataArray: string[], shardId: number): Promise<{
postInstructions: InstructionWithEphemeralSigners[];
priceFeedIdToPriceUpdateAccount: Record<string, PublicKey>;
closeInstructions: InstructionWithEphemeralSigners[];
}>;
/**
* Build a series of helper instructions that post a VAA in an encoded VAA account. This function is bespoke for posting Pyth VAAs and might not work for other usecases.
*
* @param vaa a Wormhole VAA
* @returns `encodedVaaAddress`: the address of the encoded VAA account where the VAA will be posted
* @returns `postInstructions`: the instructions to post the VAA
* @returns `closeInstructions`: the instructions to close the encoded VAA account
*/
buildPostEncodedVaaInstructions(vaa: Buffer): Promise<{
encodedVaaAddress: PublicKey;
postInstructions: InstructionWithEphemeralSigners[];
closeInstructions: InstructionWithEphemeralSigners[];
}>;
/**
* Build an instruction to close an encoded VAA account, recovering the rent.
*/
buildCloseEncodedVaaInstruction(encodedVaa: PublicKey): Promise<InstructionWithEphemeralSigners>;
/**
* Build aset of instructions to close all the existing encoded VAA accounts owned by this PythSolanaReceiver's wallet
*/
buildClosePreviousEncodedVaasInstructions(maxInstructions: number): Promise<InstructionWithEphemeralSigners[]>;
/**
* Build an instruction to close a price update account, recovering the rent.
*/
buildClosePriceUpdateInstruction(priceUpdateAccount: PublicKey): Promise<InstructionWithEphemeralSigners>;
/**
* Build an instruction to close a TWAP update account, recovering the rent.
*/
buildCloseTwapUpdateInstruction(twapUpdateAccount: PublicKey): Promise<InstructionWithEphemeralSigners>;
/**
* Returns a set of versioned transactions that contain the provided instructions in the same order and with efficient batching
*/
batchIntoVersionedTransactions(instructions: InstructionWithEphemeralSigners[], priorityFeeConfig: PriorityFeeConfig, addressLookupTable?: AddressLookupTableAccount): Promise<{
tx: VersionedTransaction;
signers: Signer[];
}[]>;
/**
* Fetch the contents of a price update account
* @param priceUpdateAccount The address of the price update account
* @returns The contents of the deserialized price update account or `null` if the account doesn't exist
*/
fetchPriceUpdateAccount(priceUpdateAccount: PublicKey): Promise<PriceUpdateAccount | null>;
/**
* Fetch the contents of a price feed account
* @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
* @param priceFeedId The price feed ID, as either a 32-byte buffer or hexadecimal string with or without a leading "0x" prefix.
* @returns The contents of the deserialized price feed account or `null` if the account doesn't exist
*/
fetchPriceFeedAccount(shardId: number, priceFeedId: Buffer | string): Promise<PriceUpdateAccount | null>;
/**
* Derive the address of a price feed account
* @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
* @param priceFeedId The price feed ID, as either a 32-byte buffer or hexadecimal string with or without a leading "0x" prefix.
* @returns The address of the price feed account
*/
getPriceFeedAccountAddress(shardId: number, priceFeedId: Buffer | string): PublicKey;
/**
* Find all the encoded VAA accounts owned by this PythSolanaReceiver's wallet
* @returns a list of the public keys of the encoded VAA accounts
*/
findOwnedEncodedVaaAccounts(): Promise<PublicKey[]>;
}
/**
* Derive the address of a price feed account
* @param shardId The shard ID of the set of price feed accounts. This shard ID allows for multiple price feed accounts for the same price feed id to exist.
* @param priceFeedId The price feed ID, as either a 32-byte buffer or hexadecimal string with or without a leading "0x" prefix.
* @param pushOracleProgramId The program ID of the Pyth Push Oracle program. If not provided, the default deployment will be used.
* @returns The address of the price feed account
*/
export declare function getPriceFeedAccountForProgram(shardId: number, priceFeedId: Buffer | string, pushOracleProgramId?: PublicKey): PublicKey;
//# sourceMappingURL=PythSolanaReceiver.d.ts.map