Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 12 additions & 12 deletions program-libs/token-interface/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,17 @@ pub enum TokenError {
#[error("Calculated top-up exceeds sender's max_top_up limit")]
MaxTopUpExceeded,

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

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

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

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

#[error("CompressedOnly tokens cannot have compressed outputs - must decompress only")]
CompressedOnlyBlocksTransfer,
Expand Down Expand Up @@ -254,10 +254,10 @@ impl From<TokenError> for u32 {
TokenError::TooManySeeds(_) => 18041,
TokenError::WriteTopUpExceedsMaximum => 18042,
TokenError::MaxTopUpExceeded => 18043,
TokenError::InvalidCMintOwner => 18044,
TokenError::CMintNotInitialized => 18045,
TokenError::CMintBorrowFailed => 18046,
TokenError::CMintDeserializationFailed => 18047,
TokenError::InvalidMintOwner => 18044,
TokenError::MintNotInitialized => 18045,
TokenError::MintBorrowFailed => 18046,
TokenError::MintDeserializationFailed => 18047,
TokenError::CompressedOnlyBlocksTransfer => 18048,
TokenError::OutTlvOutputCountMismatch => 18049,
TokenError::InLamportsUnimplemented => 18050,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ use light_compressed_account::instruction_data::{
};

use crate::instructions::mint_action::{
Action, CompressAndCloseCMintAction, CompressedMintInstructionData, CompressedMintWithContext,
CpiContext, CreateMint, DecompressMintAction, MintActionCompressedInstructionData,
MintToAction, MintToCompressedAction, RemoveMetadataKeyAction, UpdateAuthority,
UpdateMetadataAuthorityAction, UpdateMetadataFieldAction,
Action, CompressAndCloseMintAction, CpiContext, CreateMint, DecompressMintAction,
MintActionCompressedInstructionData, MintInstructionData, MintToAction, MintToCompressedAction,
MintWithContext, RemoveMetadataKeyAction, UpdateAuthority, UpdateMetadataAuthorityAction,
UpdateMetadataFieldAction,
};

/// Discriminator for MintAction instruction
Expand All @@ -22,11 +22,8 @@ impl InstructionDiscriminator for MintActionCompressedInstructionData {
impl LightInstructionData for MintActionCompressedInstructionData {}

impl MintActionCompressedInstructionData {
/// Create instruction data from CompressedMintWithContext (for existing mints)
pub fn new(
mint_with_context: CompressedMintWithContext,
proof: Option<CompressedProof>,
) -> Self {
/// Create instruction data from MintWithContext (for existing mints)
pub fn new(mint_with_context: MintWithContext, proof: Option<CompressedProof>) -> Self {
Self {
leaf_index: mint_with_context.leaf_index,
prove_by_index: mint_with_context.prove_by_index,
Expand All @@ -44,7 +41,7 @@ impl MintActionCompressedInstructionData {
pub fn new_mint(
address_merkle_tree_root_index: u16,
proof: CompressedProof,
mint: CompressedMintInstructionData,
mint: MintInstructionData,
) -> Self {
Self {
leaf_index: 0, // New mint has no existing leaf
Expand All @@ -62,7 +59,7 @@ impl MintActionCompressedInstructionData {
/// Create instruction data for new mint creation via CPI context write
pub fn new_mint_write_to_cpi_context(
address_merkle_tree_root_index: u16,
mint: CompressedMintInstructionData,
mint: MintInstructionData,
cpi_context: CpiContext,
) -> Self {
Self {
Expand Down Expand Up @@ -126,9 +123,9 @@ impl MintActionCompressedInstructionData {
self
}

#[must_use = "with_compress_and_close_cmint returns a new value"]
pub fn with_compress_and_close_cmint(mut self, action: CompressAndCloseCMintAction) -> Self {
self.actions.push(Action::CompressAndCloseCMint(action));
#[must_use = "with_compress_and_close_mint returns a new value"]
pub fn with_compress_and_close_mint(mut self, action: CompressAndCloseMintAction) -> Self {
self.actions.push(Action::CompressAndCloseMint(action));
self
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,39 @@ use light_zero_copy::ZeroCopy;

use crate::{AnchorDeserialize, AnchorSerialize};

/// Action to compress and close a CMint Solana account.
/// Action to compress and close a Mint Solana account.
/// The compressed mint state is always preserved.
///
/// ## Requirements
/// - CMint must exist (cmint_decompressed = true) - unless idempotent is set
/// - Mint must exist (mint_decompressed = true) - unless idempotent is set
/// - is_compressible() must return true (rent expired)
/// - Cannot be combined with DecompressMint in same instruction
///
/// ## Note
/// CompressAndCloseCMint is **permissionless** - anyone can compress and close a CMint
/// CompressAndCloseMint is **permissionless** - anyone can compress and close a Mint
/// provided is_compressible() returns true. All lamports are returned to rent_sponsor.
#[repr(C)]
#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, ZeroCopy)]
pub struct CompressAndCloseCMintAction {
/// If non-zero, succeed silently when CMint doesn't exist or cannot be compressed.
pub struct CompressAndCloseMintAction {
/// If non-zero, succeed silently when Mint doesn't exist or cannot be compressed.
/// Useful for foresters to handle already-compressed mints without failing.
pub idempotent: u8,
}

impl CompressAndCloseCMintAction {
impl CompressAndCloseMintAction {
/// Returns true if this action should succeed silently when:
/// - CMint doesn't exist (already compressed)
/// - CMint cannot be compressed (rent not expired)
/// - Mint doesn't exist (already compressed)
/// - Mint cannot be compressed (rent not expired)
#[inline(always)]
pub fn is_idempotent(&self) -> bool {
self.idempotent != 0
}
}

impl ZCompressAndCloseCMintAction<'_> {
impl ZCompressAndCloseMintAction<'_> {
/// Returns true if this action should succeed silently when:
/// - CMint doesn't exist (already compressed)
/// - CMint cannot be compressed (rent not expired)
/// - Mint doesn't exist (already compressed)
/// - Mint cannot be compressed (rent not expired)
#[inline(always)]
pub fn is_idempotent(&self) -> bool {
self.idempotent != 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub struct CpiContext {
pub token_out_queue_index: u8,
// Index of the compressed account that should receive the new address (0 = mint, 1+ = token accounts)
pub assigned_account_index: u8,
/// Placeholder to enable cmints in multiple address trees.
/// Placeholder to enable mints in multiple address trees.
/// Currently set to 0.
pub read_only_address_trees: [u8; 4],
pub address_tree_pubkey: [u8; 32],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ use light_zero_copy::ZeroCopy;

use crate::{AnchorDeserialize, AnchorSerialize};

/// Action to decompress a compressed mint to a CMint Solana account.
/// Creates a CMint PDA that becomes the source of truth for the mint state.
/// Action to decompress a compressed mint to a Mint Solana account.
/// Creates a Mint PDA that becomes the source of truth for the mint state.
///
/// CMint is ALWAYS compressible - `rent_payment` must be >= 2.
/// Mint is ALWAYS compressible - `rent_payment` must be >= 2.
/// rent_payment == 0 or 1 is rejected (epoch boundary edge case).
#[repr(C)]
#[derive(Debug, Clone, Copy, AnchorSerialize, AnchorDeserialize, ZeroCopy)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ use light_compressible::compression_info::CompressionInfo;
use light_zero_copy::ZeroCopy;

use super::{
CompressAndCloseCMintAction, CpiContext, DecompressMintAction, MintToAction,
CompressAndCloseMintAction, CpiContext, DecompressMintAction, MintToAction,
MintToCompressedAction, RemoveMetadataKeyAction, UpdateAuthority,
UpdateMetadataAuthorityAction, UpdateMetadataFieldAction,
};
use crate::{
instructions::extensions::{ExtensionInstructionData, ZExtensionInstructionData},
state::{
AdditionalMetadata, BaseMint, CompressedMint, CompressedMintMetadata, ExtensionStruct,
TokenMetadata,
},
state::{AdditionalMetadata, BaseMint, ExtensionStruct, Mint, MintMetadata, TokenMetadata},
AnchorDeserialize, AnchorSerialize, TokenError,
};

Expand All @@ -31,12 +28,12 @@ pub enum Action {
UpdateMetadataField(UpdateMetadataFieldAction),
UpdateMetadataAuthority(UpdateMetadataAuthorityAction),
RemoveMetadataKey(RemoveMetadataKeyAction),
/// Decompress a compressed mint to a CMint Solana account.
/// Creates a CMint PDA that becomes the source of truth.
/// Decompress a compressed mint to a Mint Solana account.
/// Creates a Mint PDA that becomes the source of truth.
DecompressMint(DecompressMintAction),
/// Compress and close a CMint Solana account. The compressed mint state is preserved.
/// Compress and close a Mint Solana account. The compressed mint state is preserved.
/// Permissionless - anyone can call if is_compressible() returns true (rent expired).
CompressAndCloseCMint(CompressAndCloseCMintAction),
CompressAndCloseMint(CompressAndCloseMintAction),
}

#[repr(C)]
Expand All @@ -56,39 +53,39 @@ pub struct MintActionCompressedInstructionData {
pub actions: Vec<Action>,
pub proof: Option<CompressedProof>,
pub cpi_context: Option<CpiContext>,
pub mint: Option<CompressedMintInstructionData>,
pub mint: Option<MintInstructionData>,
}

#[repr(C)]
#[derive(Debug, Clone, AnchorSerialize, Default, AnchorDeserialize, ZeroCopy)]
pub struct CreateMint {
/// Placeholder to enable cmints in multiple address trees.
/// Placeholder to enable mints in multiple address trees.
/// Currently set to 0.
pub read_only_address_trees: [u8; 4],
/// Placeholder to enable cmints in multiple address trees.
/// Placeholder to enable mints in multiple address trees.
/// Currently set to 0.
pub read_only_address_tree_root_indices: [u16; 4],
}

#[repr(C)]
#[derive(Debug, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy, PartialEq)]
pub struct CompressedMintWithContext {
pub struct MintWithContext {
pub leaf_index: u32,
pub prove_by_index: bool,
pub root_index: u16,
pub address: [u8; 32],
pub mint: Option<CompressedMintInstructionData>,
pub mint: Option<MintInstructionData>,
}

#[repr(C)]
#[derive(Debug, PartialEq, Eq, Clone, AnchorSerialize, AnchorDeserialize, ZeroCopy)]
pub struct CompressedMintInstructionData {
pub struct MintInstructionData {
/// Total supply of tokens.
pub supply: u64,
/// Number of base 10 digits to the right of the decimal place.
pub decimals: u8,
/// Light Protocol-specific metadata
pub metadata: CompressedMintMetadata,
pub metadata: MintMetadata,
/// Optional authority used to mint new tokens. The mint authority may only
/// be provided during mint creation. If no mint authority is present
/// then the mint has a fixed supply and no further tokens may be
Expand All @@ -100,10 +97,10 @@ pub struct CompressedMintInstructionData {
pub extensions: Option<Vec<ExtensionInstructionData>>,
}

impl TryFrom<CompressedMint> for CompressedMintInstructionData {
impl TryFrom<Mint> for MintInstructionData {
type Error = TokenError;

fn try_from(mint: CompressedMint) -> Result<Self, Self::Error> {
fn try_from(mint: Mint) -> Result<Self, Self::Error> {
let extensions = match mint.extensions {
Some(exts) if !exts.is_empty() => {
let mut extension_list = Vec::with_capacity(exts.len());
Expand Down Expand Up @@ -141,12 +138,10 @@ impl TryFrom<CompressedMint> for CompressedMintInstructionData {
}
}

impl<'a> TryFrom<&ZCompressedMintInstructionData<'a>> for CompressedMint {
impl<'a> TryFrom<&ZMintInstructionData<'a>> for Mint {
type Error = TokenError;

fn try_from(
instruction_data: &ZCompressedMintInstructionData<'a>,
) -> Result<Self, Self::Error> {
fn try_from(instruction_data: &ZMintInstructionData<'a>) -> Result<Self, Self::Error> {
let extensions = match &instruction_data.extensions {
Some(exts) => {
let converted_exts: Vec<_> = exts
Expand Down Expand Up @@ -196,9 +191,9 @@ impl<'a> TryFrom<&ZCompressedMintInstructionData<'a>> for CompressedMint {
is_initialized: true, // Always true for compressed mints
freeze_authority: instruction_data.freeze_authority.map(|p| *p),
},
metadata: CompressedMintMetadata {
metadata: MintMetadata {
version: instruction_data.metadata.version,
cmint_decompressed: instruction_data.metadata.cmint_decompressed != 0,
mint_decompressed: instruction_data.metadata.mint_decompressed != 0,
mint: instruction_data.metadata.mint,
mint_signer: instruction_data.metadata.mint_signer,
bump: instruction_data.metadata.bump,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
mod builder;
mod compress_and_close_cmint;
mod compress_and_close_mint;
mod cpi_context;
mod decompress_mint;
mod instruction_data;
Expand All @@ -8,7 +8,7 @@ mod mint_to_compressed;
mod update_metadata;
mod update_mint;

pub use compress_and_close_cmint::*;
pub use compress_and_close_mint::*;
pub use cpi_context::*;
pub use decompress_mint::*;
pub use instruction_data::*;
Expand Down
Loading