Skip to main content

percli_program/instructions/
crank.rs

1use anchor_lang::prelude::*;
2
3use crate::error::{from_risk_error, PercolatorError};
4use crate::state::{engine_from_account_data, MARKET_ACCOUNT_SIZE};
5
6#[derive(Accounts)]
7pub struct Crank<'info> {
8    /// Permissionless — anyone can crank.
9    pub cranker: Signer<'info>,
10
11    /// CHECK: Validated via discriminator and size.
12    #[account(
13        mut,
14        constraint = market.data_len() == MARKET_ACCOUNT_SIZE @ PercolatorError::AccountNotFound,
15    )]
16    pub market: UncheckedAccount<'info>,
17    // TODO: add Pyth oracle account for production
18    // pub oracle: Account<'info, PriceUpdateV2>,
19}
20
21pub fn handler(ctx: Context<Crank>, oracle_price: u64, funding_rate: i64) -> Result<()> {
22    let market = &ctx.accounts.market;
23    let mut data = market.try_borrow_mut_data()?;
24
25    require!(&data[0..8] == b"percmrkt", PercolatorError::AccountNotFound);
26
27    let engine = engine_from_account_data(&mut data);
28    let clock = Clock::get()?;
29
30    // In production, oracle_price would be read from Pyth price feed.
31    engine
32        .keeper_crank(clock.slot, oracle_price, &[], 0, funding_rate)
33        .map_err(from_risk_error)?;
34
35    Ok(())
36}