MCPcopy Create free account
hub / github.com/clockwork-xyz/examples / handler

Function handler

pyth_stats/programs/pyth_stats/src/instructions/calc.rs:65–180  ·  view source on GitHub ↗
(ctx: Context<Calc<'info>>)

Source from the content-addressed store, hash-verified

63}
64
65pub fn handler<'info>(ctx: Context<Calc<'info>>) -> Result<ThreadResponse> {
66 // get accounts
67 let avg_buffer_acc = ctx.accounts.avg_buffer.as_ref();
68 let price_buffer_acc = ctx.accounts.price_buffer.as_ref();
69 let price_feed = &ctx.accounts.price_feed;
70 let stat = &mut ctx.accounts.stat;
71 let thread = &ctx.accounts.thread;
72 let time_series_acc = ctx.accounts.time_series.as_ref();
73
74 // load mut entries
75 let mut avg_buffer = load_entries_mut::<AvgBuffer, i64>(avg_buffer_acc.try_borrow_mut_data()?).unwrap();
76 let mut price_buffer = load_entries_mut::<PriceBuffer, i64>(price_buffer_acc.try_borrow_mut_data()?).unwrap();
77 let mut time_series = load_entries_mut::<TimeSeries, i64>(time_series_acc.try_borrow_mut_data()?).unwrap();
78
79 let mut next_instruction: Option<InstructionData> = None;
80
81 match load_price_feed_from_account_info(&price_feed.to_account_info()) {
82 Ok(price_feed) => {
83 // Load Pyth price fee.
84 let price = price_feed.get_price_unchecked();
85
86 // Starting at the tail, start nullifying data points older than the lookback window.
87 // TODO This is a worst-case linear operation over a large time_series.
88 // Watch out for exceeding compute unit limits. Since this is a threaded instruction,
89 // we can run it as an infinite loop until we've cleared out all the old data.
90 match stat.head {
91 None => {}, // Noop
92 Some(head) => {
93 let mut tail = (head - stat.sample_count as i64 + 1).rem_euclid(stat.buffer_size as i64);
94 while stat.sample_count > 0 && time_series[tail as usize] < price.publish_time - stat.lookback_window {
95 stat.sample_sum -= price_buffer[tail as usize];
96 stat.sample_count -= 1;
97 price_buffer[tail as usize] = i64::default();
98 avg_buffer[tail as usize] = i64::default();
99 time_series[tail as usize] = i64::default();
100 tail = (tail + 1).rem_euclid(stat.buffer_size as i64);
101 }
102 }
103 }
104
105 // Insert the new data point, and update head.
106 match stat.head {
107 // no data present
108 None => {
109 stat.head = Some(0);
110 time_series[0] = price.publish_time;
111 price_buffer[0] = price.price;
112 stat.sample_count += 1;
113 },
114 // data present
115 Some(head) => {
116 // update head idx for next insertion
117 stat.head = Some((head + 1).rem_euclid(stat.buffer_size as i64));
118
119 // If the buffer is not yet full, increment the sample count.
120 // Otherwise, subtract the data value that's about to be overwritten from the sum.
121 if stat.sample_count < stat.buffer_size {
122 stat.sample_count += 1

Callers 3

initializeFunction · 0.50
calcFunction · 0.50
realloc_buffersFunction · 0.50

Calls

no outgoing calls

Tested by

no test coverage detected