-
Notifications
You must be signed in to change notification settings - Fork 7
Sync metadata to Spl Token #247
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0815e03
to
1643f48
Compare
/// This instruction will create the `Metaplex` metadata account if it | ||
/// doesn't exist, or update it if it does. The `wrapped_mint_authority` | ||
/// PDA must be pre-funded with enough lamports to cover the rent for | ||
/// the `Metaplex` metadata account's creation or updates, as it will | ||
/// act as the payer for the `Metaplex` program CPI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, the metaplex metadata program requires a payer for the create instruction. Pre-funding the PDA is not an option, so this instruction uses the wrapped_mint_authority PDA as the signer and requires the user to transfer to that account.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yuck, that really stinks. I don't love the solution, but I can't come up with anything better. It's slick since the wrapped mint authority is required to sign create / update metadata
/// Extracts the token metadata from the unwrapped mint | ||
pub fn extract_token_metadata<'a>( | ||
unwrapped_mint_info: &AccountInfo<'a>, | ||
source_metadata_info: Option<&AccountInfo<'a>>, | ||
owner_program_info: Option<&AccountInfo<'a>>, | ||
) -> Result<TokenMetadata, ProgramError> { | ||
let unwrapped_metadata = if *unwrapped_mint_info.owner == spl_token_2022::id() { | ||
// Source is Token-2022: resolve metadata pointer | ||
resolve_token_2022_source_metadata( | ||
unwrapped_mint_info, | ||
source_metadata_info, | ||
owner_program_info, | ||
)? | ||
} else if *unwrapped_mint_info.owner == spl_token::id() { | ||
// Source is spl-token: read from Metaplex PDA | ||
let metaplex_metadata_info = | ||
source_metadata_info.ok_or(ProgramError::NotEnoughAccountKeys)?; | ||
let (expected_metaplex_pda, _) = MetaplexMetadata::find_pda(unwrapped_mint_info.key); | ||
if *metaplex_metadata_info.owner != mpl_token_metadata::ID { | ||
return Err(ProgramError::InvalidAccountOwner); | ||
} | ||
if *metaplex_metadata_info.key != expected_metaplex_pda { | ||
return Err(TokenWrapError::MetaplexMetadataMismatch.into()); | ||
} | ||
metaplex_to_token_2022_metadata(unwrapped_mint_info, metaplex_metadata_info)? | ||
} else { | ||
return Err(ProgramError::IncorrectProgramId); | ||
}; | ||
|
||
Ok(unwrapped_metadata) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Used for both sync instructions so abstracting
@@ -0,0 +1,445 @@ | |||
use { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to the new extract_token_metadata
, this felt right extracting out to its own so that redundant tests are not needed for both sync code paths.
This is quite close to the same as the former program/tests/test_pointer_sync.rs
(deleted now) but does not use mollusk except for the CPI case for third party programs.
.execute(); | ||
} | ||
|
||
#[test] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The deleted tests here are covered in program/tests/test_extract_token_metadata.rs
now
} | ||
|
||
pub struct SyncMetadataBuilder<'a> { | ||
pub struct SyncToToken2022Builder<'a> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renaming to distinguish the two syncing builders
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great! Just a nit which can be done in a future PR
/// This instruction will create the `Metaplex` metadata account if it | ||
/// doesn't exist, or update it if it does. The `wrapped_mint_authority` | ||
/// PDA must be pre-funded with enough lamports to cover the rent for | ||
/// the `Metaplex` metadata account's creation or updates, as it will | ||
/// act as the payer for the `Metaplex` program CPI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yuck, that really stinks. I don't love the solution, but I can't come up with anything better. It's slick since the wrapped mint authority is required to sign create / update metadata
1643f48
to
acb98e7
Compare
New
SyncMetadataToSplToken
Instruction: Allows syncing metadata from unwrapped tokens to a wrapped SPL Token's Metaplex account, performing a CPI "upsert" (create or update).Also refactors and consolidates metadata reading into a universal extract_token_metadata function.