Manager
For use cases where the asset needs to be controlled (managed) by a third-party address, Nifty Asset allows the creation of "managed" assets. These assets have the Manager extension enabled, which defines a delegate address with customizable permissions.
| Field | Description |
|---|---|
delegate | Address that controls the asset. |
| A delegate is specified by: | |
address | Address of the delegate. |
roles | Bitmask of the roles enabled (Transfer, Lock and Burn). |
The delegate can perform any of the actions specified on the roles field. Therefore, when the Manager extension is present on an asset, the ownership of the asset is shared — both the owner and the delegate will be able to transfer, lock and burn the asset.
Since the presence of the Manager extension significantly changes the nature of the asset, the extension can only be added to assets with the Standard set to Managed.
The Manager extension must be specified at the point of creation of the asset. It is not possible to add or remove the extension after its creation. It is possible, however, to update the address and the roles enabled.
Using a Manager
The Manager extension is used to create Managed assets. The extension can be added using either the allocate or create instruction.
- JavaScript
- Rust
- Rust (on-chain)
import { DelegateRole, Standard, create, manager } from '@nifty-oss/asset';
await create(umi, {
asset,
owner,
name: 'Managed Asset',
standard: Standard.Managed,
payer,
extension: manager(delegate, [DelegateRole.Transfer]),
}).sendAndConfirm(umi);
use nifty_asset::{
extensions::{ManagerBuilder, ExtensionBuilder},
instructions::CreateBuilder,
types::{
Delegate,
DelegateRole,
ExtensionInput,
ExtensionType,
Standard
},
};
let mut manager = ManagerBuilder::default();
manager.set(&Delegate {
address: delegate.pubkey().into(),
roles: Delegate::encode_roles(vec![DelegateRole::Transfer]),
});
let ix = CreateBuilder::new()
.asset(asset.pubkey())
.authority(authority.pubkey(), false)
.owner(owner.pubkey())
.payer(Some(payer.pubkey()))
.system_program(Some(system_program::id()))
.name("Managed Asset".to_string())
.standard(Standard::Managed)
.extension(ExtensionInput {
extension_type: ExtensionType::Manager,
length: manager.len() as u32,
data: Some(manager),
})
.instruction();
use nifty_asset::{
extensions::{ManagerBuilder, ExtensionBuilder},
instructions::CreateCpiBuilder,
types::{
Delegate,
DelegateRole,
ExtensionInput,
ExtensionType,
Standard
},
};
let mut manager = ManagerBuilder::default();
manager.set(&Delegate {
address: delegate.pubkey().into(),
roles: Delegate::encode_roles(vec![DelegateRole::Transfer]),
});
CreateCpiBuilder::new(ctx.accounts.nifty_asset_program)
.asset(ctx.accounts.group)
.authority(ctx.accounts.authority)
.owner(ctx.accounts.owner)
.payer(Some(ctx.accounts.payer))
.system_program(Some(ctx.accounts.system_program))
.name("Managed Asset".to_string())
.standard(Standard::Managed)
.extension(ExtensionInput {
extension_type: ExtensionType::Manager,
length: manager.len() as u32,
data: Some(manager),
})
.invoke();
Fetching a Manager
Given an asset account, it is possible to retrieve the manager information of an asset. Note that not all assets might have the extension, therefore it is necessary to assert if the extension was found.
- JavaScript
- Rust
- Rust (on-chain)
import {
ExtensionType,
fetchAsset,
getExtension
} from '@nifty-oss/asset';
const asset = await fetchAsset(umi, address);
const manager = getExtension(asset, ExtensionType.Manager);
if (manager) {
console.log("Delegate: " + manager.address);
console.log("Roles: " + manager.roles);
}
use nifty_asset::{
extensions::Manager,
state::Asset,
};
let account = get_account(address)
.await
.unwrap();
let account_data = account.data.as_ref();
if let Some(manager) = Asset::get::<Manager>(account_data) {
println!("manager: {:?}", manager);
}
use nifty_asset::{
extensions::Manager,
state::Asset,
};
let data = (*ctx.accounts.asset.data).borrow();
if let Some(manager) = Asset::get::<Attributes>(&data) {
msg!("manager: {:?}", manager);
}