Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
feat: more consise pass
  • Loading branch information
stranzhay committed May 28, 2025
commit 864eb1bcb8471c693ceb27e960b930deff9bab70
4 changes: 4 additions & 0 deletions programs/mpl-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,10 @@ pub enum MplCoreError {
/// 50 - Bubblegum V2 Plugin limits other plugins
#[error("Bubblegum V2 Plugin limits other plugins")]
BlockedByBubblegumV2,

/// 51 - Group must be empty to be closed
#[error("Group must be empty to be closed")]
GroupMustBeEmpty,
}

impl PrintProgramError for MplCoreError {
Expand Down
150 changes: 142 additions & 8 deletions programs/mpl-core/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,22 @@ use borsh::{BorshDeserialize, BorshSerialize};
use shank::{ShankContext, ShankInstruction};

use crate::processor::{
AddCollectionExternalPluginAdapterV1Args, AddCollectionPluginV1Args,
AddExternalPluginAdapterV1Args, AddPluginV1Args, ApproveCollectionPluginAuthorityV1Args,
ApprovePluginAuthorityV1Args, BurnCollectionV1Args, BurnV1Args, CompressV1Args,
CreateCollectionV1Args, CreateCollectionV2Args, CreateV1Args, CreateV2Args, DecompressV1Args,
ExecuteV1Args, RemoveCollectionExternalPluginAdapterV1Args, RemoveCollectionPluginV1Args,
RemoveExternalPluginAdapterV1Args, RemovePluginV1Args, RevokeCollectionPluginAuthorityV1Args,
AddAssetsToGroupV1Args, AddCollectionExternalPluginAdapterV1Args, AddCollectionPluginV1Args,
AddCollectionsToGroupV1Args, AddExternalPluginAdapterV1Args,
AddGroupExternalPluginAdapterV1Args, AddGroupPluginV1Args, AddGroupsToGroupV1Args,
AddPluginV1Args, ApproveCollectionPluginAuthorityV1Args, ApproveGroupPluginAuthorityV1Args,
ApprovePluginAuthorityV1Args, BurnCollectionV1Args, BurnV1Args, CloseGroupV1Args,
CompressV1Args, CreateCollectionV1Args, CreateCollectionV2Args, CreateGroupV1Args,
CreateV1Args, CreateV2Args, DecompressV1Args, ExecuteV1Args, RemoveAssetsFromGroupV1Args,
RemoveCollectionExternalPluginAdapterV1Args, RemoveCollectionPluginV1Args,
RemoveCollectionsFromGroupV1Args, RemoveExternalPluginAdapterV1Args,
RemoveGroupExternalPluginAdapterV1Args, RemoveGroupPluginV1Args, RemoveGroupsFromGroupV1Args,
RemovePluginV1Args, RevokeCollectionPluginAuthorityV1Args, RevokeGroupPluginAuthorityV1Args,
RevokePluginAuthorityV1Args, TransferV1Args, UpdateCollectionExternalPluginAdapterV1Args,
UpdateCollectionInfoV1Args, UpdateCollectionPluginV1Args, UpdateCollectionV1Args,
UpdateExternalPluginAdapterV1Args, UpdatePluginV1Args, UpdateV1Args, UpdateV2Args,
WriteCollectionExternalPluginAdapterDataV1Args, WriteExternalPluginAdapterDataV1Args,
UpdateExternalPluginAdapterV1Args, UpdateGroupPluginV1Args, UpdateGroupV1Args,
UpdatePluginV1Args, UpdateV1Args, UpdateV2Args, WriteCollectionExternalPluginAdapterDataV1Args,
WriteExternalPluginAdapterDataV1Args, WriteGroupExternalPluginAdapterDataV1Args,
};

/// Instructions supported by the mpl-core program.
Expand All @@ -39,6 +45,27 @@ pub(crate) enum MplAssetInstruction {
#[account(3, name="system_program", desc = "The system program")]
CreateCollectionV1(CreateCollectionV1Args),

/// Create a new Group account.
#[account(0, writable, signer, name="group", desc = "The address of the new group")]
#[account(1, optional, name="update_authority", desc = "The authority of the new group")]
#[account(2, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(3, name="system_program", desc = "The system program")]
CreateGroupV1(CreateGroupV1Args),

/// Close an existing Group account. The group must have no parent or child relationships.
#[account(0, writable, name="group", desc = "The address of the group to close")]
#[account(1, writable, signer, name="payer", desc = "The account receiving reclaimed lamports")]
#[account(2, optional, signer, name="authority", desc = "The update authority or update delegate of the group")]
CloseGroupV1(CloseGroupV1Args),

/// Update an existing Group account.
#[account(0, writable, name="group", desc = "The address of the group to update")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or update delegate of the group")]
#[account(3, optional, name="new_update_authority", desc = "The new update authority of the group")]
#[account(4, name="system_program", desc = "The system program")]
UpdateGroupV1(UpdateGroupV1Args),

/// Add a plugin to an mpl-core.
#[account(0, writable, name="asset", desc = "The address of the asset")]
#[account(1, optional, writable, name="collection", desc = "The collection to which the asset belongs")]
Expand Down Expand Up @@ -307,4 +334,111 @@ pub(crate) enum MplAssetInstruction {
#[account(0, writable, name="collection", desc = "The address of the asset")]
#[account(1, signer, name="bubblegum_signer", desc = "Bubblegum PDA signer")]
UpdateCollectionInfoV1(UpdateCollectionInfoV1Args),

/// Add collections to a group.
#[account(0, writable, name="group", desc = "The address of the group to modify")]
#[account(1, writable, signer, name="payer", desc = "The account paying for storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group/collections")]
#[account(3, name="system_program", desc = "The system program")]
AddCollectionsToGroupV1(AddCollectionsToGroupV1Args),

/// Remove collections from a group.
#[account(0, writable, name="group", desc = "The address of the group to modify")]
#[account(1, writable, signer, name="payer", desc = "The account paying for storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group/collections")]
#[account(3, name="system_program", desc = "The system program")]
RemoveCollectionsFromGroupV1(RemoveCollectionsFromGroupV1Args),

/// Add assets to a group.
#[account(0, writable, name="group", desc = "The address of the group to modify")]
#[account(1, writable, signer, name="payer", desc = "The account paying for storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group/assets")]
#[account(3, name="system_program", desc = "The system program")]
AddAssetsToGroupV1(AddAssetsToGroupV1Args),

/// Remove assets from a group.
#[account(0, writable, name="group", desc = "The address of the group to modify")]
#[account(1, writable, signer, name="payer", desc = "The account paying for storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group/assets")]
#[account(3, name="system_program", desc = "The system program")]
RemoveAssetsFromGroupV1(RemoveAssetsFromGroupV1Args),

/// Add groups to a parent group.
#[account(0, writable, name="parent_group", desc = "The address of the parent group to modify")]
#[account(1, writable, signer, name="payer", desc = "The account paying for storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the groups")]
#[account(3, name="system_program", desc = "The system program")]
AddGroupsToGroupV1(AddGroupsToGroupV1Args),

/// Remove groups from a parent group.
#[account(0, writable, name="parent_group", desc = "The address of the parent group to modify")]
#[account(1, writable, signer, name="payer", desc = "The account paying for storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the groups")]
#[account(3, name="system_program", desc = "The system program")]
RemoveGroupsFromGroupV1(RemoveGroupsFromGroupV1Args),

/// Add a plugin to a Group account.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group")]
#[account(3, name="system_program", desc = "The system program")]
#[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")]
AddGroupPluginV1(AddGroupPluginV1Args),

/// Remove a plugin from a Group account.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group")]
#[account(3, name="system_program", desc = "The system program")]
#[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")]
RemoveGroupPluginV1(RemoveGroupPluginV1Args),

/// Update a plugin of a Group account.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group")]
#[account(3, name="system_program", desc = "The system program")]
#[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")]
UpdateGroupPluginV1(UpdateGroupPluginV1Args),

/// Approve an authority to a Group plugin.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group")]
#[account(3, name="system_program", desc = "The system program")]
#[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")]
ApproveGroupPluginAuthorityV1(ApproveGroupPluginAuthorityV1Args),

/// Revoke an authority from a Group plugin.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group")]
#[account(3, name="system_program", desc = "The system program")]
#[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")]
RevokeGroupPluginAuthorityV1(RevokeGroupPluginAuthorityV1Args),

/// Add an external plugin adapter to a Group.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group")]
#[account(3, name="system_program", desc = "The system program")]
#[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")]
AddGroupExternalPluginAdapterV1(AddGroupExternalPluginAdapterV1Args),

/// Remove an external plugin adapter from a Group.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The update authority or delegate of the group")]
#[account(3, name="system_program", desc = "The system program")]
#[account(4, optional, name="log_wrapper", desc = "The SPL Noop Program")]
RemoveGroupExternalPluginAdapterV1(RemoveGroupExternalPluginAdapterV1Args),

/// Write data to a Group external plugin adapter.
#[account(0, writable, name="group", desc = "The address of the group")]
#[account(1, writable, signer, name="payer", desc = "The account paying for the storage fees")]
#[account(2, optional, signer, name="authority", desc = "The data authority or update authority of the group")]
#[account(3, optional, name="buffer", desc = "Buffer account containing data")]
#[account(4, name="system_program", desc = "The system program")]
#[account(5, optional, name="log_wrapper", desc = "The SPL Noop Program")]
WriteGroupExternalPluginAdapterDataV1(WriteGroupExternalPluginAdapterDataV1Args),
}
25 changes: 25 additions & 0 deletions programs/mpl-core/src/plugins/internal/authority_managed/groups.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use crate::{plugins::PluginValidation, state::DataBlob};
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::pubkey::Pubkey;

/// Groups plugin for collections. Stores the immediate parent group accounts this collection
/// belongs to. Validation is deferred to specialized group instructions, so the plugin itself has
/// no special lifecycle behaviour beyond the default `PluginValidation` implementation.
#[repr(C)]
#[derive(Clone, BorshSerialize, BorshDeserialize, Debug, PartialEq, Eq, Default)]
pub struct Groups {
/// The list of parent group accounts for this collection.
pub groups: Vec<Pubkey>, // 4 + len * 32
}

impl Groups {
const BASE_LEN: usize = 4; // length of the groups vector
}

impl DataBlob for Groups {
fn len(&self) -> usize {
Self::BASE_LEN + self.groups.len() * 32
}
}

impl PluginValidation for Groups {}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod add_blocker;
mod attributes;
mod groups;
mod immutable_metadata;
mod master_edition;
mod royalties;
Expand All @@ -8,6 +9,7 @@ mod verified_creators;

pub use add_blocker::*;
pub use attributes::*;
pub use groups::*;
pub use immutable_metadata::*;
pub use master_edition::*;
pub use royalties::*;
Expand Down
12 changes: 12 additions & 0 deletions programs/mpl-core/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ pub enum Plugin {
ImmutableMetadata(ImmutableMetadata),
/// VerifiedCreators plugin allows update auth to specify verified creators and additional creators to sign
VerifiedCreators(VerifiedCreators),
/// Groups plugin stores parent group memberships of a collection for taxonomy purposes
Groups(Groups),
/// Autograph plugin allows anybody to add their signature to the asset with an optional message
Autograph(Autograph),
/// The Bubblegum V2 plugin allows a Core collection to contain Compressed NFTs (cNFTs) from the Bubblegum program.
Expand Down Expand Up @@ -104,6 +106,7 @@ impl Plugin {
Plugin::AddBlocker(inner) => inner,
Plugin::ImmutableMetadata(inner) => inner,
Plugin::VerifiedCreators(inner) => inner,
Plugin::Groups(inner) => inner,
Plugin::Autograph(inner) => inner,
Plugin::BubblegumV2(inner) => inner,
}
Expand Down Expand Up @@ -136,6 +139,7 @@ impl DataBlob for Plugin {
Plugin::AddBlocker(add_blocker) => add_blocker.len(),
Plugin::ImmutableMetadata(immutable_metadata) => immutable_metadata.len(),
Plugin::VerifiedCreators(verified_creators) => verified_creators.len(),
Plugin::Groups(groups) => groups.len(),
Plugin::Autograph(autograph) => autograph.len(),
Plugin::BubblegumV2(bubblegum_v2) => bubblegum_v2.len(),
}
Expand Down Expand Up @@ -188,6 +192,8 @@ pub enum PluginType {
ImmutableMetadata,
/// VerifiedCreators plugin.
VerifiedCreators,
/// Groups plugin.
Groups,
/// Autograph plugin.
Autograph,
/// Bubblegum V2 plugin.
Expand Down Expand Up @@ -229,6 +235,7 @@ impl From<&Plugin> for PluginType {
Plugin::Edition(_) => PluginType::Edition,
Plugin::MasterEdition(_) => PluginType::MasterEdition,
Plugin::VerifiedCreators(_) => PluginType::VerifiedCreators,
Plugin::Groups(_) => PluginType::Groups,
Plugin::Autograph(_) => PluginType::Autograph,
Plugin::BubblegumV2(_) => PluginType::BubblegumV2,
}
Expand All @@ -253,6 +260,7 @@ impl PluginType {
PluginType::Edition => Authority::UpdateAuthority,
PluginType::MasterEdition => Authority::UpdateAuthority,
PluginType::VerifiedCreators => Authority::UpdateAuthority,
PluginType::Groups => Authority::UpdateAuthority,
PluginType::Autograph => Authority::Owner,
PluginType::BubblegumV2 => Authority::Address {
address: mpl_bubblegum::ID,
Expand Down Expand Up @@ -306,6 +314,7 @@ mod test {
Plugin::AddBlocker(AddBlocker {}),
Plugin::ImmutableMetadata(ImmutableMetadata {}),
Plugin::VerifiedCreators(VerifiedCreators { signatures: vec![] }),
Plugin::Groups(Groups { groups: vec![] }),
Plugin::Autograph(Autograph { signatures: vec![] }),
Plugin::BubblegumV2(BubblegumV2 {}),
];
Expand Down Expand Up @@ -417,6 +426,9 @@ mod test {
verified: true,
}],
})],
vec![Plugin::Groups(Groups {
groups: vec![Pubkey::default()],
})],
vec![Plugin::Autograph(Autograph {
signatures: vec![AutographSignature {
address: Pubkey::default(),
Expand Down
Loading
Loading