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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#![allow(non_snake_case)]

use crate::cfg_client;
use crate::prelude::*;
use std::cell::Ref;

// VrfPoolRequestRandomness
// VrfPoolRemove
// TODO: VrfPoolAdd (Can be done off-chain)

#[repr(packed)]
#[zero_copy(unsafe)]
#[derive(Default, Debug)]
pub struct VrfPoolRow {
    pub timestamp: i64,
    pub pubkey: Pubkey,
}

#[repr(packed)]
#[account(zero_copy(unsafe))]
pub struct VrfPoolAccountData {
    /// ACCOUNTS
    pub authority: Pubkey, // authority can never be changed or else vrf accounts are useless
    pub queue: Pubkey,
    pub escrow: Pubkey, // escrow used to fund requests to reduce management

    // CONFIG
    pub min_interval: u32,
    pub max_rows: u32,

    // ITER
    pub size: u32,
    pub idx: u32,
    // Needs to be 4byte aligned up until here
    pub state_bump: u8,
    pub _ebuf: [u8; 135], // 256 bytes for pool config
}
//

impl VrfPoolAccountData {
    /// Returns the deserialized Switchboard VRF Lite account
    ///
    /// # Arguments
    ///
    /// * `switchboard_vrf` - A Solana AccountInfo referencing an existing Switchboard VRF Lite account
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use switchboard_solana::VrfPoolAccountData;
    ///
    /// let vrf = VrfPoolAccountData::new(vrf_pool_account_info)?;
    /// ```
    pub fn new<'info>(
        vrf_pool_account_info: &'info AccountInfo,
    ) -> anchor_lang::Result<Ref<'info, VrfPoolAccountData>> {
        let data = vrf_pool_account_info.try_borrow_data()?;
        if data.len() < VrfPoolAccountData::discriminator().len() {
            return Err(ErrorCode::AccountDiscriminatorNotFound.into());
        }

        let mut disc_bytes = [0u8; 8];
        disc_bytes.copy_from_slice(&data[..8]);
        if disc_bytes != VrfPoolAccountData::discriminator() {
            return Err(ErrorCode::AccountDiscriminatorMismatch.into());
        }

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

    /// Returns the deserialized Switchboard VRF Lite account
    ///
    /// # Arguments
    ///
    /// * `data` - A Solana AccountInfo's data buffer
    ///
    /// # Examples
    ///
    /// ```ignore
    /// use switchboard_solana::VrfPoolAccountData;
    ///
    /// let vrf = VrfPoolAccountData::new(vrf_pool_account_info.try_borrow_data()?)?;
    /// ```
    pub fn new_from_bytes(data: &[u8]) -> anchor_lang::Result<&VrfPoolAccountData> {
        if data.len() < VrfPoolAccountData::discriminator().len() {
            return Err(ErrorCode::AccountDiscriminatorNotFound.into());
        }

        let mut disc_bytes = [0u8; 8];
        disc_bytes.copy_from_slice(&data[..8]);
        if disc_bytes != VrfPoolAccountData::discriminator() {
            return Err(ErrorCode::AccountDiscriminatorMismatch.into());
        }

        Ok(bytemuck::from_bytes(
            &data[8..std::mem::size_of::<VrfPoolAccountData>() + 8],
        ))
    }

    cfg_client! {
        pub async fn fetch(
            client: &solana_client::rpc_client::RpcClient,
            pubkey: Pubkey,
        ) -> std::result::Result<Self, switchboard_common::Error> {
            crate::client::load_account(client, pubkey).await
        }
    }
}

// impl Discriminator for VrfPoolAccountData {
//     const DISCRIMINATOR: [u8; 8] = [86, 67, 58, 9, 46, 21, 101, 248];
// }
// impl Owner for VrfPoolAccountData {
//     fn owner() -> solana_program::pubkey::Pubkey {
//         SWITCHBOARD_PROGRAM_ID
//     }
// }

impl Default for VrfPoolAccountData {
    fn default() -> Self {
        unsafe { std::mem::zeroed() }
    }
}