spherenet-program-whitelist-interface 0.3.0

Interface of SphereNet's Program Whitelist Program
Documentation
//! Instruction types

use {
    pinocchio::{
        program_error::ProgramError,
        pubkey::{Pubkey, PUBKEY_BYTES},
    },
    shank::ShankInstruction,
};
/// Instructions supported by the program whitelist program.
#[repr(C)]
#[derive(Clone, Debug, PartialEq, ShankInstruction)]
pub enum ProgramWhitelistInstruction {
    /// Proposes a new authority for the program whitelist. The current
    /// `whitelist_authority` must sign this instruction. The proposed
    /// `new_authority` must then sign an `AcceptAuthorityTransfer`
    /// instruction to finalize the transfer.
    ///
    /// Accounts expected by this instruction:
    ///
    ///   0. `[writable]` The whitelist account
    ///   1. `[signer]` The current whitelist authority
    #[account(
        0,
        writable,
        name = "whitelist_account",
        desc = "The whitelist account"
    )]
    #[account(
        1,
        signer,
        name = "whitelist_authority",
        desc = "The whitelist authority"
    )]
    InitiateAuthorityTransfer { new_authority: Pubkey },

    /// Accepts the pending authority transfer for the program whitelist. The
    /// `pending_whitelist_authority` must sign this instruction to assume
    /// authority over the whitelist.
    ///
    /// Accounts expected by this instruction:
    ///
    ///   0. `[writable]` The whitelist account
    ///   1. `[signer]` The pending whitelist authority
    #[account(
        0,
        writable,
        name = "whitelist_account",
        desc = "The whitelist account"
    )]
    #[account(
        1,
        signer,
        name = "pending_whitelist_authority",
        desc = "The pending whitelist authority"
    )]
    AcceptAuthorityTransfer,

    /// Cancels a pending authority transfer for the program whitelist. The
    /// current `whitelist_authority` must sign this instruction.
    ///
    /// Accounts expected by this instruction:
    ///
    ///   0. `[writable]` The whitelist account
    ///   1. `[signer]` The current whitelist authority
    #[account(
        0,
        writable,
        name = "whitelist_account",
        desc = "The whitelist account"
    )]
    #[account(
        1,
        signer,
        name = "whitelist_authority",
        desc = "The whitelist authority"
    )]
    CancelAuthorityTransfer {},

    /// Requests a new entry on the program whitelist. Permissionless: the
    /// `deploy_authority` being requested must sign, proving control of the
    /// key. Creates a `Pending` entry that the `whitelist_authority` must later
    /// approve (via `ApproveWhitelistEntry`) before it grants deploy access.
    ///
    /// Accounts expected by this instruction:
    ///
    ///   0. `[signer, writable]` Payer (funds the new entry account)
    ///   1. `[signer]` The deploy authority being requested (proves key
    ///      control)
    ///   2. `[]` The whitelist account (used for validation/derivation)
    ///   3. `[writable]` The whitelist entry account to be created (Pending)
    ///   4. `[]` System program
    #[account(
        0,
        signer,
        writable,
        name = "payer",
        desc = "Payer account (funds the new entry, must be a system account)"
    )]
    #[account(
        1,
        signer,
        name = "deploy_authority",
        desc = "The deploy authority being requested (signs to prove control)"
    )]
    #[account(
        2,
        name = "whitelist_account",
        desc = "The whitelist account"
    )]
    #[account(
        3,
        writable,
        name = "whitelist_entry_account",
        desc = "The whitelist entry account"
    )]
    #[account(4, name = "system_program", desc = "System program")]
    RequestWhitelistEntry,

    /// Approves a pending whitelist entry, promoting it from `Pending` to
    /// `Approved` (active — the deploy gate then passes for that authority).
    /// The `whitelist_authority` must sign this instruction.
    ///
    /// Accounts expected by this instruction:
    ///
    ///   0. `[signer]` Payer
    ///   1. `[signer]` The whitelist authority
    ///   2. `[]` The whitelist account (used for validation)
    ///   3. `[writable]` The whitelist entry account to approve
    #[account(
        0,
        signer,
        name = "payer",
        desc = "Payer account"
    )]
    #[account(
        1,
        signer,
        name = "whitelist_authority",
        desc = "The whitelist authority"
    )]
    #[account(
        2,
        name = "whitelist_account",
        desc = "The whitelist account"
    )]
    #[account(
        3,
        writable,
        name = "whitelist_entry_account",
        desc = "The whitelist entry account to approve"
    )]
    ApproveWhitelistEntry { deploy_authority: Pubkey },

    /// Rejects a pending whitelist entry, closing it and reclaiming its rent
    /// lamports to the payer. Only a `Pending` entry may be rejected (an active
    /// `Approved` entry is removed via `RemoveWhitelistEntry`). The
    /// `whitelist_authority` must sign this instruction.
    ///
    /// Accounts expected by this instruction:
    ///
    ///   0. `[signer, writable]` Payer (receives reclaimed rent)
    ///   1. `[signer]` The whitelist authority
    ///   2. `[]` The whitelist account (used for validation)
    ///   3. `[writable]` The whitelist entry account to reject
    #[account(
        0,
        signer,
        writable,
        name = "payer",
        desc = "Payer account (receives reclaimed rent)"
    )]
    #[account(
        1,
        signer,
        name = "whitelist_authority",
        desc = "The whitelist authority"
    )]
    #[account(
        2,
        name = "whitelist_account",
        desc = "The whitelist account"
    )]
    #[account(
        3,
        writable,
        name = "whitelist_entry_account",
        desc = "The whitelist entry account to reject"
    )]
    RejectWhitelistEntry { deploy_authority: Pubkey },

    /// Closes a whitelist entry account, reclaiming its rent lamports to the
    /// payer. The `whitelist_authority` must sign this instruction.
    ///
    /// Accounts expected by this instruction:
    ///
    ///   0. `[signer, writable]` Payer (receives reclaimed rent)
    ///   1. `[signer]` The whitelist authority
    ///   2. `[]` The whitelist account (used for validation)
    ///   3. `[writable]` The whitelist entry account to close
    #[account(
        0,
        signer,
        writable,
        name = "payer",
        desc = "Payer account (receives reclaimed rent)"
    )]
    #[account(
        1,
        signer,
        name = "whitelist_authority",
        desc = "The whitelist authority"
    )]
    #[account(
        2,
        name = "whitelist_account",
        desc = "The whitelist account"
    )]
    #[account(
        3,
        writable,
        name = "whitelist_entry_account",
        desc = "The whitelist entry account to close"
    )]
    RemoveWhitelistEntry { deploy_authority: Pubkey },
}

impl ProgramWhitelistInstruction {
    /// Instruction discriminant tags — the single source of truth for the
    /// leading byte of each instruction's data. Both `unpack` (below) and the
    /// `onchain` CPI builders reference these, so a renumber happens in exactly
    /// one place. Values MUST match the enum's positional order: the shank IDL
    /// and the generated clients derive their discriminants positionally.
    pub const INITIATE_AUTHORITY_TRANSFER_TAG: u8 = 0;
    pub const ACCEPT_AUTHORITY_TRANSFER_TAG: u8 = 1;
    pub const CANCEL_AUTHORITY_TRANSFER_TAG: u8 = 2;
    pub const REQUEST_WHITELIST_ENTRY_TAG: u8 = 3;
    pub const APPROVE_WHITELIST_ENTRY_TAG: u8 = 4;
    pub const REJECT_WHITELIST_ENTRY_TAG: u8 = 5;
    pub const REMOVE_WHITELIST_ENTRY_TAG: u8 = 6;

    /// Unpack a program whitelist instruction from a byte slice.
    pub fn unpack(input: &[u8]) -> Result<Self, ProgramError> {
        let (&tag, rest) = input
            .split_first()
            .ok_or(ProgramError::InvalidInstructionData)?;
        match tag {
            Self::INITIATE_AUTHORITY_TRANSFER_TAG if rest.len() == PUBKEY_BYTES => {
                let new_authority = Pubkey::try_from(rest).unwrap();
                Ok(Self::InitiateAuthorityTransfer { new_authority })
            }
            Self::ACCEPT_AUTHORITY_TRANSFER_TAG if rest.is_empty() => {
                Ok(Self::AcceptAuthorityTransfer)
            }
            Self::CANCEL_AUTHORITY_TRANSFER_TAG if rest.is_empty() => {
                Ok(Self::CancelAuthorityTransfer {})
            }
            Self::REQUEST_WHITELIST_ENTRY_TAG if rest.is_empty() => {
                Ok(Self::RequestWhitelistEntry)
            }
            Self::APPROVE_WHITELIST_ENTRY_TAG if rest.len() == PUBKEY_BYTES => {
                let deploy_authority = Pubkey::try_from(rest).unwrap();
                Ok(Self::ApproveWhitelistEntry { deploy_authority })
            }
            Self::REJECT_WHITELIST_ENTRY_TAG if rest.len() == PUBKEY_BYTES => {
                let deploy_authority = Pubkey::try_from(rest).unwrap();
                Ok(Self::RejectWhitelistEntry { deploy_authority })
            }
            Self::REMOVE_WHITELIST_ENTRY_TAG if rest.len() == PUBKEY_BYTES => {
                let deploy_authority = Pubkey::try_from(rest).unwrap();
                Ok(Self::RemoveWhitelistEntry { deploy_authority })
            }
            _ => Err(ProgramError::InvalidInstructionData),
        }
    }
}