Skip to content
Draft
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use {
crate::instructions::extensions::token_group::state::{
offset_token_group_initialize_group as OFFSET, InstructionDiscriminatorTokenGroup,
},
pinocchio::{
account_info::AccountInfo,
cpi::invoke_signed,
instruction::{AccountMeta, Instruction, Signer},
pubkey::Pubkey,
ProgramResult,
},
};

/// Initialize a new `Group`
///
/// Assumes one has already initialized a mint for the group.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Group
/// 1. `[]` Mint
/// 2. `[signer]` Mint authority
pub struct InitializeGroup<'a, 'b> {
/// Group Account
pub group: &'a AccountInfo,
/// Mint Account
pub mint: &'a AccountInfo,
/// Mint authority
pub mint_authority: &'a AccountInfo,
/// Update authority for the group
pub update_authority: Option<&'b Pubkey>,
/// The maximum number of group members
pub max_size: u64,
/// Token Group Program
pub program_id: &'b Pubkey,
}

impl InitializeGroup<'_, '_> {
#[inline(always)]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}

#[inline(always)]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let account_metas = [
AccountMeta::writable(self.group.key()),
AccountMeta::readonly(self.mint.key()),
AccountMeta::readonly_signer(self.mint_authority.key()),
];

let mut buffer = [0u8; OFFSET::END as usize];
let data =
initialize_group_instruction_data(&mut buffer, self.update_authority, self.max_size);

let instruction = Instruction {
program_id: self.program_id,
accounts: &account_metas,
data,
};

invoke_signed(
&instruction,
&[self.group, self.mint, self.mint_authority],
signers,
)
}
}

#[inline(always)]
fn initialize_group_instruction_data<'a>(
buffer: &'a mut [u8],
update_authority: Option<&Pubkey>,
max_size: u64,
) -> &'a [u8] {
let mut offset = OFFSET::START as usize;

// Set discriminators
buffer[..offset].copy_from_slice(
&(InstructionDiscriminatorTokenGroup::InitializeGroup as u64).to_le_bytes(),
);

// Set update_authority
if let Some(x) = update_authority {
buffer[offset..offset + OFFSET::UPDATE_AUTHORITY as usize].copy_from_slice(x);
}
offset += OFFSET::UPDATE_AUTHORITY as usize;

// Set max_size
buffer[offset..offset + OFFSET::MAX_SIZE as usize].copy_from_slice(&max_size.to_le_bytes());

buffer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use {
crate::instructions::extensions::token_group::state::{
offset_token_group_initialize_member as OFFSET, InstructionDiscriminatorTokenGroup,
},
pinocchio::{
account_info::AccountInfo,
cpi::invoke_signed,
instruction::{AccountMeta, Instruction, Signer},
pubkey::Pubkey,
ProgramResult,
},
};

/// Initialize a new `Member` of a `Group`
///
/// Assumes the `Group` has already been initialized,
/// as well as the mint for the member.
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Member
/// 1. `[]` Member mint
/// 2. `[signer]` Member mint authority
/// 3. `[writable]` Group
/// 4. `[signer]` Group update authority
pub struct InitializeMember<'a, 'b> {
/// Member Account
pub member: &'a AccountInfo,
/// Member mint
pub member_mint: &'a AccountInfo,
/// Member mint authority
pub member_mint_authority: &'a AccountInfo,
/// Group Account
pub group: &'a AccountInfo,
/// Group update authority
pub group_update_authority: &'a AccountInfo,
/// Token Group Program
pub program_id: &'b Pubkey,
}

impl InitializeMember<'_, '_> {
#[inline(always)]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}

#[inline(always)]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let account_metas = [
AccountMeta::writable(self.member.key()),
AccountMeta::readonly(self.member_mint.key()),
AccountMeta::readonly_signer(self.member_mint_authority.key()),
AccountMeta::writable(self.group.key()),
AccountMeta::readonly_signer(self.group_update_authority.key()),
];

let mut buffer = [0u8; OFFSET::END as usize];
let data = initialize_member_instruction_data(&mut buffer);

let instruction = Instruction {
program_id: self.program_id,
accounts: &account_metas,
data,
};

invoke_signed(
&instruction,
&[
self.member,
self.member_mint,
self.member_mint_authority,
self.group,
self.group_update_authority,
],
signers,
)
}
}

#[inline(always)]
fn initialize_member_instruction_data<'a>(buffer: &'a mut [u8]) -> &'a [u8] {
let offset = OFFSET::START as usize;

// Set discriminators
buffer[..offset].copy_from_slice(
&(InstructionDiscriminatorTokenGroup::InitializeMember as u64).to_le_bytes(),
);

buffer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mod initialize_group;
mod initialize_member;
mod update_group_authority;
mod update_max_size;

pub use initialize_group::*;
pub use initialize_member::*;
pub use update_group_authority::*;
pub use update_max_size::*;
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use {
crate::instructions::extensions::token_group::state::{
offset_token_group_update_authority as OFFSET, InstructionDiscriminatorTokenGroup,
},
pinocchio::{
account_info::AccountInfo,
cpi::invoke_signed,
instruction::{AccountMeta, Instruction, Signer},
pubkey::Pubkey,
ProgramResult,
},
};

/// Update the authority of a `Group`
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Group
/// 1. `[signer]` Current update authority
pub struct UpdateGroupAuthority<'a, 'b> {
/// Group Account
pub group: &'a AccountInfo,
/// Current update authority
pub current_authority: &'a AccountInfo,
/// New authority for the group, or None to unset
pub new_authority: Option<&'b Pubkey>,
/// Token Group Program
pub program_id: &'b Pubkey,
}

impl UpdateGroupAuthority<'_, '_> {
#[inline(always)]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}

#[inline(always)]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let account_metas = [
AccountMeta::writable(self.group.key()),
AccountMeta::readonly_signer(self.current_authority.key()),
];

let mut buffer = [0u8; OFFSET::END as usize];
let data = update_group_authority_instruction_data(&mut buffer, self.new_authority);

let instruction = Instruction {
program_id: self.program_id,
accounts: &account_metas,
data,
};

invoke_signed(&instruction, &[self.group, self.current_authority], signers)
}
}

#[inline(always)]
fn update_group_authority_instruction_data<'a>(
buffer: &'a mut [u8],
new_authority: Option<&Pubkey>,
) -> &'a [u8] {
let offset = OFFSET::START as usize;

// Set discriminators
buffer[..offset].copy_from_slice(
&(InstructionDiscriminatorTokenGroup::UpdateGroupAuthority as u64).to_le_bytes(),
);

// Set new_authority (optional)
if let Some(authority) = new_authority {
buffer[offset..offset + OFFSET::NEW_AUTHORITY as usize].copy_from_slice(authority.as_ref());
}

buffer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
use {
crate::instructions::extensions::token_group::state::{
offset_token_group_update_max_size as OFFSET, InstructionDiscriminatorTokenGroup,
},
pinocchio::{
account_info::AccountInfo,
cpi::invoke_signed,
instruction::{AccountMeta, Instruction, Signer},
pubkey::Pubkey,
ProgramResult,
},
};

/// Update the max size of a `Group`
///
/// Accounts expected by this instruction:
///
/// 0. `[writable]` Group
/// 1. `[signer]` Update authority
pub struct UpdateGroupMaxSize<'a, 'b> {
/// Group Account
pub group: &'a AccountInfo,
// /// Update authority
pub update_authority: &'a AccountInfo,
/// New max size for the group
pub max_size: u64,
/// Token Group Program
pub program_id: &'b Pubkey,
}

impl UpdateGroupMaxSize<'_, '_> {
#[inline(always)]
pub fn invoke(&self) -> ProgramResult {
self.invoke_signed(&[])
}

#[inline(always)]
pub fn invoke_signed(&self, signers: &[Signer]) -> ProgramResult {
let account_metas = [
AccountMeta::writable(self.group.key()),
AccountMeta::readonly_signer(self.update_authority.key()),
];

let mut buffer = [0u8; OFFSET::END as usize];
let data = update_group_max_size_instruction_data(&mut buffer, self.max_size);

let instruction = Instruction {
program_id: self.program_id,
accounts: &account_metas,
data,
};

invoke_signed(&instruction, &[self.group, self.update_authority], signers)
}
}

#[inline(always)]
fn update_group_max_size_instruction_data<'a>(buffer: &'a mut [u8], max_size: u64) -> &'a [u8] {
let offset = OFFSET::START as usize;

// Set discriminators
buffer[..offset].copy_from_slice(
&(InstructionDiscriminatorTokenGroup::UpdateGroupMaxSize as u64).to_le_bytes(),
);

// Set max_size
buffer[offset..offset + OFFSET::MAX_SIZE as usize].copy_from_slice(&max_size.to_le_bytes());

buffer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pub mod instructions;
pub mod state;

pub use instructions::*;
pub use state::*;
Loading