1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use crate::*;
use crate::pubkey::Pubkey;
use std::cell::Ref;
use solana_program::clock::Clock;

#[derive(Clone, Copy, Debug, bytemuck::Pod, bytemuck::Zeroable)]
#[repr(C)]
pub struct RandomnessAccountData {
    pub authority: Pubkey,
    pub queue: Pubkey,

    pub seed_slothash: [u8; 32],
    pub seed_slot: u64,
    pub oracle: Pubkey,

    pub reveal_slot: u64,
    pub value: [u8; 32],

    _ebuf2: [u8; 96],
    _ebuf1: [u8; 128],
}
impl Discriminator for RandomnessAccountData {
    const DISCRIMINATOR: [u8; 8] = [10, 66, 229, 135, 220, 239, 217, 114];
}
impl Owner for RandomnessAccountData {
    fn owner() -> Pubkey {
        *SWITCHBOARD_ON_DEMAND_PROGRAM_ID
    }
}

cfg_client! {
    impl_account_deserialize!(RandomnessAccountData);
}
impl RandomnessAccountData {
    pub const fn size() -> usize {
        std::mem::size_of::<Self>() + 8
    }

    pub fn get_value(&self, clock: &Clock) -> std::result::Result<[u8; 32], OnDemandError> {
        if clock.slot != self.reveal_slot {
            return Err(OnDemandError::SwitchboardRandomnessTooOld.into());
        }
        Ok(self.value)
    }

    pub fn is_revealable(&self, clock: &Clock) -> bool {
        self.seed_slot < clock.slot
    }

    pub fn parse<'info>(
        data: Ref<'info, &mut [u8]>,
    ) -> std::result::Result<Ref<'info, Self>, OnDemandError> {
        if data.len() < Self::discriminator().len() {
            return Err(OnDemandError::InvalidDiscriminator);
        }

        let mut disc_bytes = [0u8; 8];
        disc_bytes.copy_from_slice(&data[..8]);
        if disc_bytes != Self::discriminator() {
            return Err(OnDemandError::InvalidDiscriminator);
        }

        Ok(Ref::map(data, |data: &&mut [u8]| {
            bytemuck::from_bytes(&data[8..std::mem::size_of::<Self>() + 8])
        }))
    }

    cfg_client! {
        pub async fn fetch_async(
            client: &solana_client::nonblocking::rpc_client::RpcClient,
            pubkey: Pubkey,
        ) -> std::result::Result<Self, crate::OnDemandError> {
            crate::client::fetch_zerocopy_account_async(client, pubkey).await
        }
    }
}