Skip to content

Commit

Permalink
Allow updating token manager kind if unclaimed (#406)
Browse files Browse the repository at this point in the history
* Allow updating token manager kind if unclaimed

* Update peek on unissue

* Update all kinds

* Update peeking and utils
  • Loading branch information
jpbogle authored Feb 13, 2023
1 parent 0bbaac8 commit 24c8e99
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 79 deletions.
89 changes: 48 additions & 41 deletions programs/cardinal-token-manager/src/instructions/invalidate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,40 @@ pub struct InvalidateCtx<'info> {

pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts, 'remaining, 'info, InvalidateCtx<'info>>) -> Result<()> {
let token_manager = &mut ctx.accounts.token_manager;
let remaining_accs = &mut ctx.remaining_accounts.iter();
let remaining_accs = &mut ctx.remaining_accounts.iter().peekable();

// get PDA seeds to sign with
let mint = token_manager.mint;
let token_manager_seeds = &[TOKEN_MANAGER_SEED.as_bytes(), mint.as_ref(), &[token_manager.bump]];
let token_manager_signer = &[&token_manager_seeds[..]];

if token_manager.kind != TokenManagerKind::Programmable as u8 {
// look at next account
if let Some(next_account) = remaining_accs.peek() {
match assert_derivation(
&mpl_token_metadata::id(),
&next_account.to_account_info(),
&[mpl_token_metadata::state::PREFIX.as_bytes(), mpl_token_metadata::id().as_ref(), mint.as_ref()],
) {
// migrated pnft
Ok(_) => {
let mint_metadata_data = next_account.try_borrow_mut_data().expect("Failed to borrow data");
let metadata = Metadata::deserialize(&mut mint_metadata_data.as_ref()).expect("Failed to deserialize metadata");
match metadata.token_standard {
Some(TokenStandard::ProgrammableNonFungible) => {
// pop this account and update type
next_account_info(remaining_accs)?;
token_manager.kind = TokenManagerKind::Programmable as u8;
}
_ => return Err(error!(ErrorCode::InvalidTokenManagerKind)),
}
}
// regular edition
_ => {}
}
}
}

if token_manager.state == TokenManagerState::Claimed as u8 {
match token_manager.kind {
k if k == TokenManagerKind::Unmanaged as u8 => {}
Expand Down Expand Up @@ -89,47 +116,27 @@ pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts,
}
k if k == TokenManagerKind::Edition as u8 => {
let edition_info = next_account_info(remaining_accs)?;
match assert_derivation(
&mpl_token_metadata::id(),
&edition_info.to_account_info(),
&[mpl_token_metadata::state::PREFIX.as_bytes(), mpl_token_metadata::id().as_ref(), ctx.accounts.mint.key().as_ref()],
) {
// migrated pnft
Ok(_) => {
let mint_metadata_data = edition_info.try_borrow_mut_data().expect("Failed to borrow data");
let metadata = Metadata::deserialize(&mut mint_metadata_data.as_ref()).expect("Failed to deserialize metadata");
match metadata.token_standard {
Some(TokenStandard::ProgrammableNonFungible) => {
token_manager.kind = TokenManagerKind::Programmable as u8;
}
_ => return Err(error!(ErrorCode::InvalidTokenManagerKind)),
}
}
// regular edition
_ => {
let metadata_program = next_account_info(remaining_accs)?;
// edition will be validated by metadata_program
if metadata_program.key() != mpl_token_metadata::id() {
return Err(error!(ErrorCode::InvalidMetadataProgramId));
}
invoke_signed(
&thaw_delegated_account(
*metadata_program.key,
token_manager.key(),
ctx.accounts.recipient_token_account.key(),
*edition_info.key,
ctx.accounts.mint.key(),
),
&[
token_manager.to_account_info(),
ctx.accounts.recipient_token_account.to_account_info(),
edition_info.to_account_info(),
ctx.accounts.mint.to_account_info(),
],
&[token_manager_seeds],
)?;
}
let metadata_program = next_account_info(remaining_accs)?;
// edition will be validated by metadata_program
if metadata_program.key() != mpl_token_metadata::id() {
return Err(error!(ErrorCode::InvalidMetadataProgramId));
}
invoke_signed(
&thaw_delegated_account(
*metadata_program.key,
token_manager.key(),
ctx.accounts.recipient_token_account.key(),
*edition_info.key,
ctx.accounts.mint.key(),
),
&[
token_manager.to_account_info(),
ctx.accounts.recipient_token_account.to_account_info(),
edition_info.to_account_info(),
ctx.accounts.mint.to_account_info(),
],
&[token_manager_seeds],
)?;
}
k if k == TokenManagerKind::Programmable as u8 => {}
_ => return Err(error!(ErrorCode::InvalidTokenManagerKind)),
Expand Down
40 changes: 22 additions & 18 deletions programs/cardinal-token-manager/src/instructions/unissue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,34 +32,38 @@ pub struct UnissueCtx<'info> {
}

pub fn handler<'key, 'accounts, 'remaining, 'info>(ctx: Context<'key, 'accounts, 'remaining, 'info, UnissueCtx<'info>>) -> Result<()> {
let remaining_accs = &mut ctx.remaining_accounts.iter();
let remaining_accs = &mut ctx.remaining_accounts.iter().peekable();
let token_manager = &mut ctx.accounts.token_manager;

// get PDA seeds to sign with
let mint = token_manager.mint;
let token_manager_seeds = &[TOKEN_MANAGER_SEED.as_bytes(), mint.as_ref(), &[token_manager.bump]];
let token_manager_signer = &[&token_manager_seeds[..]];

if token_manager.kind == TokenManagerKind::Edition as u8 {
let edition_info = next_account_info(remaining_accs)?;
match assert_derivation(
&mpl_token_metadata::id(),
&edition_info.to_account_info(),
&[mpl_token_metadata::state::PREFIX.as_bytes(), mpl_token_metadata::id().as_ref(), mint.as_ref()],
) {
// migrated pnft
Ok(_) => {
let mint_metadata_data = edition_info.try_borrow_mut_data().expect("Failed to borrow data");
let metadata = Metadata::deserialize(&mut mint_metadata_data.as_ref()).expect("Failed to deserialize metadata");
match metadata.token_standard {
Some(TokenStandard::ProgrammableNonFungible) => {
token_manager.kind = TokenManagerKind::Programmable as u8;
if token_manager.kind != TokenManagerKind::Programmable as u8 {
// look at next account
if let Some(next_account) = remaining_accs.peek() {
match assert_derivation(
&mpl_token_metadata::id(),
&next_account.to_account_info(),
&[mpl_token_metadata::state::PREFIX.as_bytes(), mpl_token_metadata::id().as_ref(), mint.as_ref()],
) {
// migrated pnft
Ok(_) => {
let mint_metadata_data = next_account.try_borrow_mut_data().expect("Failed to borrow data");
let metadata = Metadata::deserialize(&mut mint_metadata_data.as_ref()).expect("Failed to deserialize metadata");
match metadata.token_standard {
Some(TokenStandard::ProgrammableNonFungible) => {
// pop this account and update type
next_account_info(remaining_accs)?;
token_manager.kind = TokenManagerKind::Programmable as u8;
}
_ => return Err(error!(ErrorCode::InvalidTokenManagerKind)),
}
_ => return Err(error!(ErrorCode::InvalidTokenManagerKind)),
}
// regular edition
_ => {}
}
// regular edition
_ => {}
}
}

Expand Down
40 changes: 20 additions & 20 deletions src/programs/tokenManager/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,19 +51,17 @@ export const getRemainingAccountsForKind = (
tokenManagerKind === TokenManagerKind.Managed ||
tokenManagerKind === TokenManagerKind.Permissioned
) {
const mintManagerId = findMintManagerId(mintId);
return [
{
pubkey: mintManagerId,
pubkey: findMintManagerId(mintId),
isSigner: false,
isWritable: true,
},
];
} else if (tokenManagerKind === TokenManagerKind.Edition) {
const editionId = findMintEditionId(mintId);
return [
{
pubkey: editionId,
pubkey: findMintEditionId(mintId),
isSigner: false,
isWritable: false,
},
Expand All @@ -85,7 +83,7 @@ export const getRemainingAccountsForUnissue = (
): AccountMeta[] => {
const remainingAccounts: AccountMeta[] = [];
if (
tokenManagerData.kind === TokenManagerKind.Edition &&
tokenManagerData.kind !== TokenManagerKind.Programmable &&
metadata?.tokenStandard === TokenStandard.ProgrammableNonFungible
) {
remainingAccounts.push({
Expand Down Expand Up @@ -169,22 +167,25 @@ export const withRemainingAccountsForInvalidate = async (
metadata: Metadata | null
): Promise<AccountMeta[]> => {
const remainingAccounts: AccountMeta[] = [];
if (
tokenManagerData.parsed.kind !== TokenManagerKind.Programmable &&
metadata?.tokenStandard === TokenStandard.ProgrammableNonFungible
) {
// update kind
tokenManagerData.parsed.kind = TokenManagerKind.Programmable;
remainingAccounts.push({
pubkey: findMintMetadataId(mintId),
isSigner: false,
isWritable: false,
});
}

if (tokenManagerData.parsed.state === TokenManagerState.Claimed) {
if (
tokenManagerData.parsed.kind === TokenManagerKind.Edition &&
metadata?.tokenStandard === TokenStandard.ProgrammableNonFungible
) {
remainingAccounts.push({
pubkey: findMintMetadataId(mintId),
isSigner: false,
isWritable: false,
});
} else {
remainingAccounts.push(
...getRemainingAccountsForKind(mintId, tokenManagerData.parsed.kind)
);
}
remainingAccounts.push(
...getRemainingAccountsForKind(mintId, tokenManagerData.parsed.kind)
);
}

if (
tokenManagerData.parsed.invalidationType === InvalidationType.Release &&
tokenManagerData.parsed.kind === TokenManagerKind.Programmable
Expand All @@ -209,7 +210,6 @@ export const withRemainingAccountsForInvalidate = async (
);
remainingAccounts.push(...returnAccounts);
}

return remainingAccounts;
};

Expand Down

0 comments on commit 24c8e99

Please sign in to comment.