Skip to content
Merged
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
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion toolbox/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name = "tensor-toolbox"
description = "Toolbox of useful Rust utilities for Tensor Foundation's Solana programs"
repository = "https://github.com/tensor-foundation/toolbox"
homepage = "https://github.com/tensor-foundation/toolbox"
version = "0.7.1"
version = "0.8.0"
edition = "2021"
readme = "../README.md"
license = "Apache-2.0"
Expand Down
6 changes: 6 additions & 0 deletions toolbox/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,10 @@ pub enum TensorError {

#[msg("invalid whitelist")]
InvalidWhitelist = 9010,

#[msg("invalid program owner")]
InvalidProgramOwner = 9011,

#[msg("invalid edition")]
InvalidEdition = 9012,
}
6 changes: 3 additions & 3 deletions toolbox/src/metaplex_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ pub fn validate_core_asset(
assert_ownership(asset_info, Key::AssetV1)?;

// validates the collection is owned by the MPL Core program
maybe_collection_info
.as_ref()
.map(|c| assert_ownership(c, Key::CollectionV1));
if let Some(collection_info) = maybe_collection_info {
assert_ownership(collection_info, Key::CollectionV1)?;
}

let asset = BaseAssetV1::try_from(asset_info)?;

Expand Down
36 changes: 33 additions & 3 deletions toolbox/src/token_metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ use anchor_spl::{
token_interface::{self, Mint, TokenAccount, TokenInterface, TransferChecked},
};
use mpl_token_metadata::{
accounts::Metadata,
accounts::{Edition, MasterEdition, Metadata},
instructions::{DelegateTransferV1CpiBuilder, TransferV1CpiBuilder},
types::{AuthorizationData, TokenStandard},
types::{AuthorizationData, Key as MplKey, TokenStandard},
};
use tensor_vipers::{throw_err, unwrap_opt};

Expand All @@ -20,7 +20,7 @@ pub use mpl_token_metadata::ID;
#[inline(never)]
pub fn assert_decode_metadata(mint: &Pubkey, metadata: &AccountInfo) -> Result<Metadata> {
if *metadata.owner != mpl_token_metadata::ID {
throw_err!(TensorError::BadMetadata);
throw_err!(TensorError::InvalidProgramOwner);
}

// We must use `safe_deserialize` since there are variations on the metadata struct
Expand All @@ -36,6 +36,36 @@ pub fn assert_decode_metadata(mint: &Pubkey, metadata: &AccountInfo) -> Result<M
Ok(metadata)
}

#[inline(never)]
pub fn assert_decode_master_edition(edition: &AccountInfo) -> Result<MasterEdition> {
if *edition.owner != mpl_token_metadata::ID {
throw_err!(TensorError::InvalidProgramOwner);
}

let edition = MasterEdition::safe_deserialize(&edition.try_borrow_data()?)
.map_err(|_error| TensorError::InvalidEdition)?;

Ok(edition)
}

#[inline(never)]
pub fn assert_decode_edition(edition: &AccountInfo) -> Result<Edition> {
if *edition.owner != mpl_token_metadata::ID {
throw_err!(TensorError::InvalidProgramOwner);
}

let data = edition.try_borrow_data()?;

if data.is_empty() || data[0] != MplKey::EditionV1 as u8 {
throw_err!(TensorError::InvalidEdition);
}

let edition = Edition::from_bytes(&edition.try_borrow_data()?)
.map_err(|_error| TensorError::InvalidEdition)?;

Ok(edition)
}

/// Transfer Args using AccountInfo types to be more generic.
pub struct TransferArgsAi<'a, 'info> {
/// Account that will pay for any associated fees.
Expand Down
Loading