Skip to content

Commit 0980475

Browse files
Add Solana TWAP documentation (#650)
* Add Solana TWAP documentation Co-Authored-By: Tejas Badadare <[email protected]> * Fix formatting issues in Solana TWAP documentation Co-Authored-By: Tejas Badadare <[email protected]> * Add references to example scripts for Hermes client and Solana TWAP Co-Authored-By: Tejas Badadare <[email protected]> * Fix formatting in skipPreflight option Co-Authored-By: Tejas Badadare <[email protected]> * Address PR comments: Move TWAP limitation to main paragraph, remove unused parameter, mention similarity to regular price updates Co-Authored-By: Tejas Badadare <[email protected]> * Clarify that the Solana TWAP example is an existing demo with added functionality Co-Authored-By: Tejas Badadare <[email protected]> * clarify example --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Tejas Badadare <[email protected]> Co-authored-by: Tejas Badadare <[email protected]>
1 parent f48fc0c commit 0980475

File tree

1 file changed

+130
-0
lines changed

1 file changed

+130
-0
lines changed

pages/price-feeds/use-real-time-data/solana.mdx

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,136 @@ The [SDK documentation](https://github.com/pyth-network/pyth-crosschain/tree/mai
241241
partially verified price updates.
242242
</Callout>
243243

244+
## Time-Weighted Average Price (TWAP)
245+
246+
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).
247+
248+
### Using TWAP in Solana Programs
249+
250+
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.
251+
252+
```rust copy
253+
use pyth_solana_receiver_sdk::price_update::{TwapUpdate};
254+
255+
#[derive(Accounts)]
256+
#[instruction(twap_window_seconds: u64)]
257+
pub struct SampleWithTwap<'info> {
258+
#[account(mut)]
259+
pub payer: Signer<'info>,
260+
// Add this account to any instruction Context that needs TWAP data
261+
pub twap_update: Account<'info, TwapUpdate>,
262+
}
263+
```
264+
265+
Update your instruction logic to read the TWAP from the update account:
266+
267+
```rust copy
268+
pub fn sample_with_twap(
269+
ctx: Context<SampleWithTwap>,
270+
twap_window_seconds: u64,
271+
) -> Result<()> {
272+
let twap_update = &mut ctx.accounts.twap_update;
273+
// get_twap_no_older_than will fail if the price update is more than 30 seconds old
274+
let maximum_age: u64 = 30;
275+
// Specify the price feed ID and the window in seconds for the TWAP
276+
let feed_id: [u8; 32] = get_feed_id_from_hex("0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43")?;
277+
let price = twap_update.get_twap_no_older_than(
278+
&Clock::get()?,
279+
maximum_age,
280+
twap_window_seconds,
281+
&feed_id,
282+
)?;
283+
284+
// Sample output:
285+
// The TWAP price is (7160106530699 ± 5129162301) * 10^-8
286+
msg!("The TWAP price is ({} ± {}) * 10^{}", price.price, price.conf, price.exponent);
287+
288+
Ok(())
289+
}
290+
```
291+
292+
### Fetching and Posting TWAP Updates
293+
294+
To use TWAP updates in your application, you need to fetch them from Hermes and post them to Solana:
295+
296+
#### Fetch TWAP updates from Hermes
297+
298+
Use `HermesClient` from `@pythnetwork/hermes-client` to fetch TWAP updates:
299+
300+
```typescript copy
301+
import { HermesClient } from "@pythnetwork/hermes-client";
302+
303+
// The URL below is a public Hermes instance operated by the Pyth Data Association.
304+
// Hermes is also available from several third-party providers listed here:
305+
// https://docs.pyth.network/price-feeds/api-instances-and-providers/hermes
306+
const hermesClient = new HermesClient("https://hermes.pyth.network/", {});
307+
308+
// Specify the price feed ID and the TWAP window in seconds (maximum 600 seconds)
309+
const twapWindowSeconds = 300; // 5 minutes
310+
const twapUpdateData = await hermesClient.getLatestTwaps(
311+
["0xe62df6c8b4a85fe1a67db44dc12de5db330f7ac66b72dc658afedf0f4a415b43"], // BTC/USD feed ID
312+
twapWindowSeconds,
313+
{ encoding: "base64" }
314+
);
315+
316+
// TWAP updates are strings of base64-encoded binary data
317+
console.log(twapUpdateData.binary.data);
318+
```
319+
320+
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.
321+
322+
#### Post TWAP updates to Solana
323+
324+
Use `PythSolanaReceiver` to post the TWAP updates and consume them in your application:
325+
326+
```typescript copy
327+
import { PythSolanaReceiver } from "@pythnetwork/pyth-solana-receiver";
328+
329+
// You will need a Connection from @solana/web3.js and a Wallet from @coral-xyz/anchor
330+
const connection: Connection;
331+
const wallet: Wallet;
332+
const pythSolanaReceiver = new PythSolanaReceiver({ connection, wallet });
333+
334+
// Create a transaction builder
335+
const transactionBuilder = pythSolanaReceiver.newTransactionBuilder({
336+
closeUpdateAccounts: false,
337+
});
338+
339+
// Add the TWAP update to the transaction
340+
await transactionBuilder.addPostTwapUpdates(twapUpdateData.binary.data);
341+
342+
// Add your application's instructions that use the TWAP update
343+
await transactionBuilder.addTwapConsumerInstructions(
344+
async (
345+
getTwapUpdateAccount: (priceFeedId: string) => PublicKey
346+
): Promise<InstructionWithEphemeralSigners[]> => {
347+
// Generate instructions here that use the TWAP updates posted above
348+
// getTwapUpdateAccount(<price feed id>) will give you the account for each TWAP update
349+
return []; // Replace with your actual instructions
350+
}
351+
);
352+
353+
// Send the instructions
354+
await pythSolanaReceiver.provider.sendAll(
355+
await transactionBuilder.buildVersionedTransactions({
356+
computeUnitPriceMicroLamports: 50000,
357+
}),
358+
{ skipPreflight: true }
359+
);
360+
```
361+
362+
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.
363+
364+
### Example Application
365+
366+
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:
367+
368+
- A React frontend for interacting with the contract
369+
- A Solana program that consumes TWAP updates
370+
- Complete transaction building for posting and consuming TWAP data
371+
372+
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.
373+
244374
## Additional Resources
245375

246376
You may find these additional resources helpful for developing your Solana application.

0 commit comments

Comments
 (0)