use satellite_lang::arch_program::program_pack::{IsInitialized, Pack};
use satellite_lang::prelude::{
AccountInfo, AccountMeta, Accounts, CpiContext, Pubkey, Result, ToAccountInfos,
};
use satellite_lang::system_program::SYSTEM_PROGRAM_ID;
pub use apl_token_metadata as arch_md;
pub use arch_md::id as ID;
pub fn create_metadata<'info>(
ctx: CpiContext<'_, '_, '_, 'info, CreateMetadata<'info>>,
name: String,
symbol: String,
image: String,
description: String,
immutable: bool,
) -> Result<()> {
let ix_data = arch_md::instruction::MetadataInstruction::CreateMetadata {
name,
symbol,
image,
description,
immutable,
}
.pack();
let ix = satellite_lang::arch_program::instruction::Instruction {
program_id: arch_md::id(),
accounts: vec![
AccountMeta::new(*ctx.accounts.payer.key, true),
AccountMeta::new_readonly(SYSTEM_PROGRAM_ID, false),
AccountMeta::new_readonly(*ctx.accounts.mint.key, false),
AccountMeta::new(*ctx.accounts.metadata.key, false),
AccountMeta::new_readonly(*ctx.accounts.mint_authority.key, true),
],
data: ix_data,
};
satellite_lang::arch_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn update_metadata<'info>(
ctx: CpiContext<'_, '_, '_, 'info, UpdateMetadata<'info>>,
name: Option<String>,
symbol: Option<String>,
image: Option<String>,
description: Option<String>,
) -> Result<()> {
let ix_data = arch_md::instruction::MetadataInstruction::UpdateMetadata {
name,
symbol,
image,
description,
}
.pack();
let ix = satellite_lang::arch_program::instruction::Instruction {
program_id: arch_md::id(),
accounts: vec![
AccountMeta::new(*ctx.accounts.metadata.key, false),
AccountMeta::new_readonly(*ctx.accounts.update_authority.key, true),
],
data: ix_data,
};
satellite_lang::arch_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn create_attributes<'info>(
ctx: CpiContext<'_, '_, '_, 'info, CreateAttributes<'info>>,
data: Vec<(String, String)>,
) -> Result<()> {
let ix_data = arch_md::instruction::MetadataInstruction::CreateAttributes { data }.pack();
let ix = satellite_lang::arch_program::instruction::Instruction {
program_id: arch_md::id(),
accounts: vec![
AccountMeta::new(*ctx.accounts.payer.key, true),
AccountMeta::new_readonly(satellite_lang::system_program::SYSTEM_PROGRAM_ID, false),
AccountMeta::new_readonly(*ctx.accounts.mint.key, false),
AccountMeta::new(*ctx.accounts.attributes.key, false),
AccountMeta::new_readonly(*ctx.accounts.update_authority.key, true),
AccountMeta::new_readonly(*ctx.accounts.metadata.key, false),
],
data: ix_data,
};
satellite_lang::arch_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn replace_attributes<'info>(
ctx: CpiContext<'_, '_, '_, 'info, ReplaceAttributes<'info>>,
data: Vec<(String, String)>,
) -> Result<()> {
let ix_data = arch_md::instruction::MetadataInstruction::ReplaceAttributes { data }.pack();
let ix = satellite_lang::arch_program::instruction::Instruction {
program_id: arch_md::id(),
accounts: vec![
AccountMeta::new(*ctx.accounts.attributes.key, false),
AccountMeta::new_readonly(*ctx.accounts.update_authority.key, true),
AccountMeta::new_readonly(*ctx.accounts.metadata.key, false),
],
data: ix_data,
};
satellite_lang::arch_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn transfer_authority<'info>(
ctx: CpiContext<'_, '_, '_, 'info, TransferAuthority<'info>>,
new_authority: Pubkey,
) -> Result<()> {
let ix_data = arch_md::instruction::MetadataInstruction::TransferAuthority { new_authority };
let ix = satellite_lang::arch_program::instruction::Instruction {
program_id: arch_md::id(),
accounts: vec![
AccountMeta::new(*ctx.accounts.metadata.key, false),
AccountMeta::new_readonly(*ctx.accounts.current_authority.key, true),
],
data: ix_data.pack(),
};
satellite_lang::arch_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
)
.map_err(Into::into)
}
pub fn make_immutable<'info>(
ctx: CpiContext<'_, '_, '_, 'info, MakeImmutable<'info>>,
) -> Result<()> {
let ix_data = arch_md::instruction::MetadataInstruction::MakeImmutable.pack();
let ix = satellite_lang::arch_program::instruction::Instruction {
program_id: arch_md::id(),
accounts: vec![
AccountMeta::new(*ctx.accounts.metadata.key, false),
AccountMeta::new_readonly(*ctx.accounts.current_authority.key, true),
],
data: ix_data,
};
satellite_lang::arch_program::program::invoke_signed(
&ix,
&ToAccountInfos::to_account_infos(&ctx),
ctx.signer_seeds,
)
.map_err(Into::into)
}
#[derive(Accounts)]
pub struct CreateMetadata<'info> {
pub payer: AccountInfo<'info>, pub system_program: AccountInfo<'info>, pub mint: AccountInfo<'info>, pub metadata: AccountInfo<'info>, pub mint_authority: AccountInfo<'info>, }
#[derive(Accounts)]
pub struct UpdateMetadata<'info> {
pub metadata: AccountInfo<'info>, pub update_authority: AccountInfo<'info>, }
#[derive(Accounts)]
pub struct CreateAttributes<'info> {
pub payer: AccountInfo<'info>, pub system_program: AccountInfo<'info>, pub mint: AccountInfo<'info>, pub attributes: AccountInfo<'info>, pub update_authority: AccountInfo<'info>, pub metadata: AccountInfo<'info>, }
#[derive(Accounts)]
pub struct ReplaceAttributes<'info> {
pub attributes: AccountInfo<'info>, pub update_authority: AccountInfo<'info>, pub metadata: AccountInfo<'info>, }
#[derive(Accounts)]
pub struct TransferAuthority<'info> {
pub metadata: AccountInfo<'info>, pub current_authority: AccountInfo<'info>, }
#[derive(Accounts)]
pub struct MakeImmutable<'info> {
pub metadata: AccountInfo<'info>, pub current_authority: AccountInfo<'info>, }
#[derive(Clone)]
pub struct ArchMetadata;
impl satellite_lang::Id for ArchMetadata {
fn id() -> Pubkey {
arch_md::id()
}
}
use satellite_lang::error::ErrorCode;
use std::ops::Deref;
#[derive(Clone, Debug, PartialEq)]
pub struct ArchTokenMetadataAccount(arch_md::state::TokenMetadata);
impl satellite_lang::AccountDeserialize for ArchTokenMetadataAccount {
fn try_deserialize(buf: &mut &[u8]) -> satellite_lang::Result<Self> {
let md = Self::try_deserialize_unchecked(buf)?;
if !md.0.is_initialized() {
return Err(ErrorCode::AccountNotInitialized.into());
}
Ok(md)
}
fn try_deserialize_unchecked(buf: &mut &[u8]) -> satellite_lang::Result<Self> {
let md = arch_md::state::TokenMetadata::unpack_from_slice(buf)
.map_err(satellite_lang::error::Error::from)?;
Ok(Self(md))
}
}
impl satellite_lang::AccountSerialize for ArchTokenMetadataAccount {}
impl satellite_lang::Owner for ArchTokenMetadataAccount {
fn owner() -> Pubkey {
arch_md::id()
}
}
impl Deref for ArchTokenMetadataAccount {
type Target = arch_md::state::TokenMetadata;
fn deref(&self) -> &Self::Target {
&self.0
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct ArchTokenMetadataAttributesAccount(arch_md::state::TokenMetadataAttributes);
impl satellite_lang::AccountDeserialize for ArchTokenMetadataAttributesAccount {
fn try_deserialize(buf: &mut &[u8]) -> satellite_lang::Result<Self> {
let acc = Self::try_deserialize_unchecked(buf)?;
if !acc.0.is_initialized() {
return Err(ErrorCode::AccountNotInitialized.into());
}
Ok(acc)
}
fn try_deserialize_unchecked(buf: &mut &[u8]) -> satellite_lang::Result<Self> {
let acc = arch_md::state::TokenMetadataAttributes::unpack_from_slice(buf)
.map_err(satellite_lang::error::Error::from)?;
Ok(Self(acc))
}
}
impl satellite_lang::AccountSerialize for ArchTokenMetadataAttributesAccount {}
impl satellite_lang::Owner for ArchTokenMetadataAttributesAccount {
fn owner() -> Pubkey {
arch_md::id()
}
}
impl Deref for ArchTokenMetadataAttributesAccount {
type Target = arch_md::state::TokenMetadataAttributes;
fn deref(&self) -> &Self::Target {
&self.0
}
}