From 0c8893dd83eae80a20ff22e731c687c58c7279b6 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 20:36:11 +0000 Subject: [PATCH 1/7] Add Solana TWAP documentation Co-Authored-By: Tejas Badadare --- .../price-feeds/use-real-time-data/solana.mdx | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/pages/price-feeds/use-real-time-data/solana.mdx b/pages/price-feeds/use-real-time-data/solana.mdx index 0b76f6a2..d03e05c3 100644 --- a/pages/price-feeds/use-real-time-data/solana.mdx +++ b/pages/price-feeds/use-real-time-data/solana.mdx @@ -241,6 +241,140 @@ The [SDK documentation](https://github.com/pyth-network/pyth-crosschain/tree/mai partially verified price updates. +## Time-Weighted Average Price (TWAP) + +Pyth also provides Time-Weighted Average Price (TWAP) for Solana applications. TWAP represents the average price over a specified time window, which can be useful for reducing the impact of short-term price volatility. + + + The TWAP window is currently limited to a maximum of 10 minutes (600 seconds). + + +### Using TWAP in Solana Programs + +To use TWAP in your Solana program, import the `TwapUpdate` struct from the Pyth Solana receiver SDK: + +```rust copy +use pyth_solana_receiver_sdk::price_update::{TwapUpdate}; + +#[derive(Accounts)] +#[instruction(amount_in_usd : u64, twap_window_seconds: u64)] +pub struct SampleWithTwap<'info> { + #[account(mut)] + pub payer: Signer<'info>, + // Add this account to any instruction Context that needs TWAP data + pub twap_update: Account<'info, TwapUpdate>, +} +``` + +Update your instruction logic to read the TWAP from the update account: + +```rust copy +pub fn sample_with_twap( + ctx: Context, + amount_in_usd: u64, + twap_window_seconds: u64, +) -> Result<()> { + let twap_update = &mut ctx.accounts.twap_update; + // get_twap_no_older_than will fail if the price update is more than 30 seconds old + let maximum_age: u64 = 30; + // Specify the price feed ID and the window in seconds for the TWAP + let feed_id: [u8; 32] = get_feed_id_from_hex("0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43")?; + let price = twap_update.get_twap_no_older_than( + &Clock::get()?, + maximum_age, + twap_window_seconds, + &feed_id, + )?; + + // Sample output: + // The TWAP price is (7160106530699 ± 5129162301) * 10^-8 + msg!("The TWAP price is ({} ± {}) * 10^{}", price.price, price.conf, price.exponent); + + Ok(()) +} +``` + +### Fetching and Posting TWAP Updates + +To use TWAP updates in your application, you need to fetch them from Hermes and post them to Solana: + +#### Fetch TWAP updates from Hermes + +Use `HermesClient` from `@pythnetwork/hermes-client` to fetch TWAP updates: + +```typescript copy +import { HermesClient } from "@pythnetwork/hermes-client"; + +// The URL below is a public Hermes instance operated by the Pyth Data Association. +// Hermes is also available from several third-party providers listed here: +// https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes +const hermesClient = new HermesClient( + "https://hermes.pyth.network/", + {} +); + +// Specify the price feed ID and the TWAP window in seconds (maximum 600 seconds) +const twapWindowSeconds = 300; // 5 minutes +const twapUpdateData = await hermesClient.getLatestTwaps( + ["0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"], // BTC/USD feed ID + twapWindowSeconds, + { encoding: "base64" } +); + +// TWAP updates are strings of base64-encoded binary data +console.log(twapUpdateData.binary.data); +``` + +#### Post TWAP updates to Solana + +Use `PythSolanaReceiver` to post the TWAP updates and consume them in your application: + +```typescript copy +import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver"; + +// You will need a Connection from @solana/web3.js and a Wallet from @coral-xyz/anchor +const connection: Connection; +const wallet: Wallet; +const pythSolanaReceiver = new PythSolanaReceiver({ connection, wallet }); + +// Create a transaction builder +const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({ + closeUpdateAccounts: false, +}); + +// Add the TWAP update to the transaction +await transactionBuilder.addPostTwapUpdates(twapUpdateData.binary.data); + +// Add your application's instructions that use the TWAP update +await transactionBuilder.addTwapConsumerInstructions( + async ( + getTwapUpdateAccount: (priceFeedId: string) => PublicKey + ): Promise => { + // Generate instructions here that use the TWAP updates posted above + // getTwapUpdateAccount() will give you the account for each TWAP update + return []; // Replace with your actual instructions + } +); + +// Send the instructions +await pythSolanaReceiver.provider.sendAll( + await transactionBuilder.buildVersionedTransactions({ + computeUnitPriceMicroLamports: 50000, + }), + { skipPreflight: true } +); +``` + +### Example Application + +The [Solana TWAP example](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/solana/send_usd) demonstrates how to fetch TWAP data from Hermes, post it to Solana, and consume it from a smart contract. The example includes: + +- A React frontend for interacting with the contract +- A Solana program that consumes TWAP updates +- Complete transaction building for posting and consuming TWAP data + +The example allows users to send a USD-denominated amount of SOL using either spot prices or TWAP prices, demonstrating how TWAP can be used to reduce the impact of price volatility. + ## Additional Resources You may find these additional resources helpful for developing your Solana application. From 8d43b1b22ab1d4b7a9ad1d0f68470081931cbb61 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 20:37:57 +0000 Subject: [PATCH 2/7] Fix formatting issues in Solana TWAP documentation Co-Authored-By: Tejas Badadare --- pages/price-feeds/use-real-time-data/solana.mdx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/pages/price-feeds/use-real-time-data/solana.mdx b/pages/price-feeds/use-real-time-data/solana.mdx index d03e05c3..5887622d 100644 --- a/pages/price-feeds/use-real-time-data/solana.mdx +++ b/pages/price-feeds/use-real-time-data/solana.mdx @@ -285,7 +285,7 @@ pub fn sample_with_twap( twap_window_seconds, &feed_id, )?; - + // Sample output: // The TWAP price is (7160106530699 ± 5129162301) * 10^-8 msg!("The TWAP price is ({} ± {}) * 10^{}", price.price, price.conf, price.exponent); @@ -308,16 +308,13 @@ import { HermesClient } from "@pythnetwork/hermes-client"; // The URL below is a public Hermes instance operated by the Pyth Data Association. // Hermes is also available from several third-party providers listed here: // https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes -const hermesClient = new HermesClient( - "https://hermes.pyth.network/", - {} -); +const hermesClient = new HermesClient("https://hermes.pyth.network/", {}); // Specify the price feed ID and the TWAP window in seconds (maximum 600 seconds) const twapWindowSeconds = 300; // 5 minutes const twapUpdateData = await hermesClient.getLatestTwaps( ["0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"], // BTC/USD feed ID - twapWindowSeconds, + twapWindowSeconds, { encoding: "base64" } ); From a7269f25373acac93293a5ce621fde2c330e450e Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 20:41:08 +0000 Subject: [PATCH 3/7] Add references to example scripts for Hermes client and Solana TWAP Co-Authored-By: Tejas Badadare --- pages/price-feeds/use-real-time-data/solana.mdx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pages/price-feeds/use-real-time-data/solana.mdx b/pages/price-feeds/use-real-time-data/solana.mdx index 5887622d..026d9f0d 100644 --- a/pages/price-feeds/use-real-time-data/solana.mdx +++ b/pages/price-feeds/use-real-time-data/solana.mdx @@ -322,6 +322,8 @@ const twapUpdateData = await hermesClient.getLatestTwaps( console.log(twapUpdateData.binary.data); ``` +For a complete example of fetching TWAP updates from Hermes, see the [HermesClient example script](https://github.com/pyth-network/pyth-crosschain/blob/main/apps/hermes/client/js/src/examples/HermesClient.ts) in the Pyth crosschain repository. + #### Post TWAP updates to Solana Use `PythSolanaReceiver` to post the TWAP updates and consume them in your application: @@ -358,10 +360,12 @@ await pythSolanaReceiver.provider.sendAll( await transactionBuilder.buildVersionedTransactions({ computeUnitPriceMicroLamports: 50000, }), - { skipPreflight: true } + { skipPreflight: true } ); ``` +For a complete example of posting TWAP updates to Solana, see the [post_twap_update.ts example script](https://github.com/pyth-network/pyth-crosschain/blob/main/target_chains/solana/sdk/js/pyth_solana_receiver/examples/post_twap_update.ts) in the Pyth crosschain repository. + ### Example Application The [Solana TWAP example](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/solana/send_usd) demonstrates how to fetch TWAP data from Hermes, post it to Solana, and consume it from a smart contract. The example includes: From 6449055d7b2ca2dc2d4df533fb270d4aae3804fc Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 20:42:10 +0000 Subject: [PATCH 4/7] Fix formatting in skipPreflight option Co-Authored-By: Tejas Badadare --- pages/price-feeds/use-real-time-data/solana.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/price-feeds/use-real-time-data/solana.mdx b/pages/price-feeds/use-real-time-data/solana.mdx index 026d9f0d..6b6587bf 100644 --- a/pages/price-feeds/use-real-time-data/solana.mdx +++ b/pages/price-feeds/use-real-time-data/solana.mdx @@ -360,7 +360,7 @@ await pythSolanaReceiver.provider.sendAll( await transactionBuilder.buildVersionedTransactions({ computeUnitPriceMicroLamports: 50000, }), - { skipPreflight: true } + { skipPreflight: true } ); ``` From 2d21106ae425a7f0f15746462be3680765d5054d Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 20:54:26 +0000 Subject: [PATCH 5/7] Address PR comments: Move TWAP limitation to main paragraph, remove unused parameter, mention similarity to regular price updates Co-Authored-By: Tejas Badadare --- pages/price-feeds/use-real-time-data/solana.mdx | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/pages/price-feeds/use-real-time-data/solana.mdx b/pages/price-feeds/use-real-time-data/solana.mdx index 6b6587bf..9d4dfd6a 100644 --- a/pages/price-feeds/use-real-time-data/solana.mdx +++ b/pages/price-feeds/use-real-time-data/solana.mdx @@ -243,21 +243,17 @@ The [SDK documentation](https://github.com/pyth-network/pyth-crosschain/tree/mai ## Time-Weighted Average Price (TWAP) -Pyth also provides Time-Weighted Average Price (TWAP) for Solana applications. TWAP represents the average price over a specified time window, which can be useful for reducing the impact of short-term price volatility. - - - The TWAP window is currently limited to a maximum of 10 minutes (600 seconds). - +Pyth also provides Time-Weighted Average Price (TWAP) for Solana applications. TWAP represents the average price over a specified time window, which can be useful for reducing the impact of short-term price volatility. The TWAP window is currently limited to a maximum of 10 minutes (600 seconds). ### Using TWAP in Solana Programs -To use TWAP in your Solana program, import the `TwapUpdate` struct from the Pyth Solana receiver SDK: +To use TWAP in your Solana program, import the `TwapUpdate` struct from the Pyth Solana receiver SDK. The process for fetching and posting TWAP updates is similar to regular price updates from Hermes. ```rust copy use pyth_solana_receiver_sdk::price_update::{TwapUpdate}; #[derive(Accounts)] -#[instruction(amount_in_usd : u64, twap_window_seconds: u64)] +#[instruction(twap_window_seconds: u64)] pub struct SampleWithTwap<'info> { #[account(mut)] pub payer: Signer<'info>, @@ -271,7 +267,6 @@ Update your instruction logic to read the TWAP from the update account: ```rust copy pub fn sample_with_twap( ctx: Context, - amount_in_usd: u64, twap_window_seconds: u64, ) -> Result<()> { let twap_update = &mut ctx.accounts.twap_update; From 05a352c98dd98d252e8f9e6705558a6026343bc3 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 22:13:09 +0000 Subject: [PATCH 6/7] Clarify that the Solana TWAP example is an existing demo with added functionality Co-Authored-By: Tejas Badadare --- pages/price-feeds/use-real-time-data/solana.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/price-feeds/use-real-time-data/solana.mdx b/pages/price-feeds/use-real-time-data/solana.mdx index 9d4dfd6a..202ebbf2 100644 --- a/pages/price-feeds/use-real-time-data/solana.mdx +++ b/pages/price-feeds/use-real-time-data/solana.mdx @@ -363,7 +363,7 @@ For a complete example of posting TWAP updates to Solana, see the [post_twap_upd ### Example Application -The [Solana TWAP example](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/solana/send_usd) demonstrates how to fetch TWAP data from Hermes, post it to Solana, and consume it from a smart contract. The example includes: +The [Solana TWAP example](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/solana/send_usd) is an existing demo application that has been enhanced with TWAP functionality. It demonstrates how to fetch TWAP data from Hermes, post it to Solana, and consume it from a smart contract. The example includes: - A React frontend for interacting with the contract - A Solana program that consumes TWAP updates From 89cf7b09377343610a8a1a3181209f69085b007a Mon Sep 17 00:00:00 2001 From: Tejas Badadare <17058023+tejasbadadare@users.noreply.github.com> Date: Sun, 30 Mar 2025 13:31:39 -0700 Subject: [PATCH 7/7] clarify example --- pages/price-feeds/use-real-time-data/solana.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/price-feeds/use-real-time-data/solana.mdx b/pages/price-feeds/use-real-time-data/solana.mdx index 202ebbf2..0d81369e 100644 --- a/pages/price-feeds/use-real-time-data/solana.mdx +++ b/pages/price-feeds/use-real-time-data/solana.mdx @@ -363,7 +363,7 @@ For a complete example of posting TWAP updates to Solana, see the [post_twap_upd ### Example Application -The [Solana TWAP example](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/solana/send_usd) is an existing demo application that has been enhanced with TWAP functionality. It demonstrates how to fetch TWAP data from Hermes, post it to Solana, and consume it from a smart contract. The example includes: +See an end-to-end example of using Price Update Accounts for spot prices or TWAP Accounts for time-averaged prices in the [SendUSD Solana Demo App](https://github.com/pyth-network/pyth-examples/tree/main/price_feeds/solana/send_usd). It demonstrates how to fetch data from Hermes, post it to Solana, and consume it from a smart contract. The example includes: - A React frontend for interacting with the contract - A Solana program that consumes TWAP updates