light-token-interface 0.5.0

Light Protocol token instruction data types.
Documentation
use light_zero_copy::errors::ZeroCopyError;
use thiserror::Error;

#[derive(Debug, PartialEq, Error)]
pub enum TokenError {
    #[error("Invalid instruction data provided")]
    InvalidInstructionData,

    #[error("Invalid account data format")]
    InvalidAccountData,

    #[error("Arithmetic operation resulted in overflow")]
    ArithmeticOverflow,

    #[error("Failed to compute hash for data")]
    HashComputationError,

    #[error("Invalid or malformed extension data")]
    InvalidExtensionData,

    #[error("Missing required mint authority")]
    MissingMintAuthority,

    #[error("Missing required freeze authority")]
    MissingFreezeAuthority,

    #[error("Invalid metadata pointer configuration")]
    InvalidMetadataPointer,

    #[error("Token metadata validation failed")]
    InvalidTokenMetadata,

    #[error("Insufficient token supply for operation")]
    InsufficientSupply,

    #[error("Token account is frozen and cannot be modified")]
    AccountFrozen,

    #[error("Invalid compressed proof provided")]
    InvalidProof,

    #[error("Address derivation failed")]
    AddressDerivationFailed,

    #[error("Extension type not supported")]
    UnsupportedExtension,

    #[error("Maximum number of extensions exceeded")]
    TooManyExtensions,

    #[error("Invalid merkle tree root index")]
    InvalidRootIndex,

    #[error("Compressed account data size exceeds limit")]
    DataSizeExceeded,

    #[error("Invalid compression mode")]
    InvalidCompressionMode,

    #[error("Insufficient funds for compression.")]
    CompressInsufficientFunds,

    #[error("Failed to access sysvar")]
    SysvarAccessError,

    #[error("Compressed token account TLV is unimplemented.")]
    CompressedTokenAccountTlvUnimplemented,

    #[error("Input accounts lamports length mismatch")]
    InputAccountsLamportsLengthMismatch,

    #[error("Output accounts lamports length mismatch")]
    OutputAccountsLamportsLengthMismatch,

    #[error("Invalid token data version")]
    InvalidTokenDataVersion,

    #[error("Instruction data expected mint authority")]
    InstructionDataExpectedMintAuthority,

    #[error("Zero-copy expected mint authority")]
    ZeroCopyExpectedMintAuthority,

    #[error("Instruction data expected freeze authority")]
    InstructionDataExpectedFreezeAuthority,

    #[error("Zero-copy expected mint authority")]
    ZeroCopyExpectedFreezeAuthority,

    #[error("Invalid authority type provided")]
    InvalidAuthorityType,

    #[error("Expected mint signer account")]
    ExpectedMintSignerAccount,

    #[error("Light hasher error: {0}")]
    HasherError(#[from] light_hasher::HasherError),

    #[error("Light zero copy error: {0}")]
    ZeroCopyError(#[from] ZeroCopyError),

    #[error("Light compressed account error: {0}")]
    CompressedAccountError(#[from] light_compressed_account::CompressedAccountError),

    #[error("Invalid token metadata version")]
    InvalidTokenMetadataVersion,
    #[error("InvalidExtensionConfig")]
    InvalidExtensionConfig,
    #[error("InstructionDataExpectedDelegate")]
    InstructionDataExpectedDelegate,
    #[error("ZeroCopyExpectedDelegate")]
    ZeroCopyExpectedDelegate,
    #[error("Unsupported TLV extension type - only CompressedOnly is currently implemented")]
    UnsupportedTlvExtensionType,
    #[error("InvalidAccountState")]
    InvalidAccountState,
    #[error("BorshFailed")]
    BorshFailed,
    #[error(
        "Too many input compressed accounts. Maximum 8 input accounts allowed per instruction"
    )]
    TooManyInputAccounts,

    #[error("Too many additional metadata elements. Maximum 20 allowed")]
    TooManyAdditionalMetadata,

    #[error("Duplicate metadata key found in additional metadata")]
    DuplicateMetadataKey,

    #[error("Too many PDA seeds. Maximum {0} seeds allowed")]
    TooManySeeds(usize),

    #[error("write_top_up exceeds max_top_up from RentConfig")]
    WriteTopUpExceedsMaximum,

    #[error("Calculated top-up exceeds sender's max_top_up limit")]
    MaxTopUpExceeded,

    #[error("Mint account has invalid owner")]
    InvalidMintOwner,

    #[error("Mint account is not initialized")]
    MintNotInitialized,

    #[error("Failed to borrow Mint account data")]
    MintBorrowFailed,

    #[error("Failed to deserialize Mint account data")]
    MintDeserializationFailed,

    #[error("CompressedOnly tokens cannot have compressed outputs - must decompress only")]
    CompressedOnlyBlocksTransfer,

    #[error("Output TLV data count must match number of compressed outputs")]
    OutTlvOutputCountMismatch,

    #[error("in_lamports field is not yet implemented")]
    InLamportsUnimplemented,

    #[error("out_lamports field is not yet implemented")]
    OutLamportsUnimplemented,

    #[error("TLV extension length mismatch - exactly one extension required")]
    TlvExtensionLengthMismatch,

    #[error("InvalidAccountType")]
    InvalidAccountType,

    #[error("Duplicate compression_index found in input TLV data")]
    DuplicateCompressionIndex,

    #[error("Decompress destination Token is not a fresh account")]
    DecompressDestinationNotFresh,

    #[error("Token account missing required Compressible extension")]
    MissingCompressibleExtension,

    #[error("Decompress destination doesn't match source account")]
    DecompressDestinationMismatch,

    #[error("Token account mint does not match expected mint")]
    MintMismatch,

    #[error("Decompress has delegated_amount but no delegate pubkey provided")]
    DecompressDelegatedAmountWithoutDelegate,

    #[error(
        "Decompress has withheld_transfer_fee but destination lacks TransferFeeAccount extension"
    )]
    DecompressWithheldFeeWithoutExtension,

    #[error("Missing required payer account")]
    MissingPayer,

    #[error("Failed to borrow account data")]
    BorrowFailed,

    #[error("Token account has invalid owner")]
    InvalidTokenOwner,

    #[error("Decompress amount mismatch between compression instruction and input token data")]
    DecompressAmountMismatch,

    #[error("Compression index exceeds maximum allowed value")]
    CompressionIndexOutOfBounds,

    #[error("ATA derivation failed or mismatched for is_ata compressed token")]
    InvalidAtaDerivation,
}

impl From<TokenError> for u32 {
    fn from(e: TokenError) -> u32 {
        match e {
            TokenError::InvalidInstructionData => 18001,
            TokenError::InvalidAccountData => 18002,
            TokenError::ArithmeticOverflow => 18003,
            TokenError::HashComputationError => 18004,
            TokenError::InvalidExtensionData => 18005,
            TokenError::MissingMintAuthority => 18006,
            TokenError::MissingFreezeAuthority => 18007,
            TokenError::InvalidMetadataPointer => 18008,
            TokenError::InvalidTokenMetadata => 18009,
            TokenError::InsufficientSupply => 18010,
            TokenError::AccountFrozen => 18011,
            TokenError::InvalidProof => 18012,
            TokenError::AddressDerivationFailed => 18013,
            TokenError::UnsupportedExtension => 18014,
            TokenError::TooManyExtensions => 18015,
            TokenError::InvalidRootIndex => 18016,
            TokenError::DataSizeExceeded => 18017,
            TokenError::InvalidCompressionMode => 18018,
            TokenError::CompressInsufficientFunds => 18019,
            TokenError::SysvarAccessError => 18020,
            TokenError::CompressedTokenAccountTlvUnimplemented => 18021,
            TokenError::InputAccountsLamportsLengthMismatch => 18022,
            TokenError::OutputAccountsLamportsLengthMismatch => 18023,
            TokenError::InvalidTokenDataVersion => 18028,
            TokenError::InstructionDataExpectedMintAuthority => 18024,
            TokenError::ZeroCopyExpectedMintAuthority => 18025,
            TokenError::InstructionDataExpectedFreezeAuthority => 18026,
            TokenError::ZeroCopyExpectedFreezeAuthority => 18027,
            TokenError::InvalidAuthorityType => 18029,
            TokenError::ExpectedMintSignerAccount => 18030,
            TokenError::InvalidTokenMetadataVersion => 18031,
            TokenError::InvalidExtensionConfig => 18032,
            TokenError::InstructionDataExpectedDelegate => 18033,
            TokenError::ZeroCopyExpectedDelegate => 18034,
            TokenError::UnsupportedTlvExtensionType => 18035,
            TokenError::InvalidAccountState => 18036,
            TokenError::BorshFailed => 18037,
            TokenError::TooManyInputAccounts => 18038,
            TokenError::TooManyAdditionalMetadata => 18039,
            TokenError::DuplicateMetadataKey => 18040,
            TokenError::TooManySeeds(_) => 18041,
            TokenError::WriteTopUpExceedsMaximum => 18042,
            TokenError::MaxTopUpExceeded => 18043,
            TokenError::InvalidMintOwner => 18044,
            TokenError::MintNotInitialized => 18045,
            TokenError::MintBorrowFailed => 18046,
            TokenError::MintDeserializationFailed => 18047,
            TokenError::CompressedOnlyBlocksTransfer => 18048,
            TokenError::OutTlvOutputCountMismatch => 18049,
            TokenError::InLamportsUnimplemented => 18050,
            TokenError::OutLamportsUnimplemented => 18051,
            TokenError::TlvExtensionLengthMismatch => 18052,
            TokenError::InvalidAccountType => 18053,
            TokenError::DuplicateCompressionIndex => 18054,
            TokenError::DecompressDestinationNotFresh => 18055,
            TokenError::MissingCompressibleExtension => 18056,
            TokenError::DecompressDestinationMismatch => 18057,
            TokenError::MintMismatch => 18058,
            TokenError::DecompressDelegatedAmountWithoutDelegate => 18059,
            TokenError::DecompressWithheldFeeWithoutExtension => 18060,
            TokenError::MissingPayer => 18061,
            TokenError::BorrowFailed => 18062,
            TokenError::InvalidTokenOwner => 18063,
            TokenError::DecompressAmountMismatch => 18064,
            TokenError::CompressionIndexOutOfBounds => 18065,
            TokenError::InvalidAtaDerivation => 18066,
            TokenError::HasherError(e) => u32::from(e),
            TokenError::ZeroCopyError(e) => u32::from(e),
            TokenError::CompressedAccountError(e) => u32::from(e),
        }
    }
}

#[cfg(all(feature = "solana", not(feature = "anchor")))]
impl From<TokenError> for solana_program_error::ProgramError {
    fn from(e: TokenError) -> Self {
        solana_program_error::ProgramError::Custom(e.into())
    }
}

impl From<TokenError> for pinocchio::program_error::ProgramError {
    fn from(e: TokenError) -> Self {
        pinocchio::program_error::ProgramError::Custom(e.into())
    }
}

#[cfg(feature = "anchor")]
impl From<TokenError> for anchor_lang::prelude::ProgramError {
    fn from(e: TokenError) -> Self {
        anchor_lang::prelude::ProgramError::Custom(e.into())
    }
}