Skip to content

Commit 0c8893d

Browse files
Add Solana TWAP documentation
Co-Authored-By: Tejas Badadare <[email protected]>
1 parent 8bcea4b commit 0c8893d

File tree

1 file changed

+134
-0
lines changed

1 file changed

+134
-0
lines changed

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

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

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

0 commit comments

Comments
 (0)