Transfers ownership of the aseet to a new public key. ### Accounts: 0. `[writable]` asset 1. `[signer]` signer 2. `[]` recipient 3. `[optional]` group_asset
(program_id: &Pubkey, ctx: Context<Transfer>)
| 32 | /// 2. `[]` recipient |
| 33 | /// 3. `[optional]` group_asset |
| 34 | pub fn process_transfer(program_id: &Pubkey, ctx: Context<Transfer>) -> ProgramResult { |
| 35 | require!( |
| 36 | ctx.accounts.asset.owner() == program_id, |
| 37 | ProgramError::IllegalOwner, |
| 38 | "asset" |
| 39 | ); |
| 40 | |
| 41 | // Account must be a signer. |
| 42 | require!( |
| 43 | ctx.accounts.signer.is_signer(), |
| 44 | ProgramError::MissingRequiredSignature, |
| 45 | "signer" |
| 46 | ); |
| 47 | |
| 48 | let mut data = ctx.accounts.asset.try_borrow_mut_data()?; |
| 49 | |
| 50 | // Must be an initialized asset. |
| 51 | require!( |
| 52 | data.len() >= Asset::LEN && data[0] == Discriminator::Asset.into(), |
| 53 | AssetError::Uninitialized, |
| 54 | "asset" |
| 55 | ); |
| 56 | |
| 57 | // First we check if the asset itself has the royalties extension, and validate the constraint. |
| 58 | let royalties_checked = process_royalties!(ctx, &data); |
| 59 | |
| 60 | let (asset, extensions) = data.split_at_mut(Asset::LEN); |
| 61 | let asset = Asset::load_mut(asset); |
| 62 | |
| 63 | // Cannot transfer soulbound assets. |
| 64 | require!( |
| 65 | asset.standard != Standard::Soulbound, |
| 66 | AssetError::CannotTransferSoulbound, |
| 67 | "soulbound asset" |
| 68 | ); |
| 69 | |
| 70 | let is_allowed = asset.owner == *ctx.accounts.signer.key() |
| 71 | || assert_delegate( |
| 72 | &[ |
| 73 | asset.delegate.value(), |
| 74 | Extension::get::<Manager>(extensions).map(|s| s.delegate), |
| 75 | ], |
| 76 | ctx.accounts.signer.key(), |
| 77 | DelegateRole::Transfer, |
| 78 | ) |
| 79 | .is_ok(); |
| 80 | |
| 81 | // Signing account must be owner or a transfer delegate. |
| 82 | require!( |
| 83 | is_allowed, |
| 84 | AssetError::InvalidTransferAuthority, |
| 85 | "not an owner or transfer delegate" |
| 86 | ); |
| 87 | |
| 88 | // Self transfer short-circuits so as not to clear the delegate. |
| 89 | if asset.owner == *ctx.accounts.recipient.key() { |
| 90 | return Ok(()); |
| 91 | } |
no test coverage detected