Properties
The Properties extension allows creating a list of on-chain "typed" values (key/value pairs) for an asset. It currently supports three different "types": text, number (as an u64 value) and boolean. The on-chain aspect means these values can be read by other Solana programs and therefore be used by them (e.g., for gaming).
The extension consists of a list of name and value pairs (Property):
| Field | Description |
|---|---|
values[0..n] | List of Property objects. |
Each Property object is represented by: | |
name | Name of the property. |
value | The "typed" value associated with the property. |
Creating Properties
The Properties extension can be created using either the allocate, create or update instructions.
- JavaScript
- Rust
- Rust (on-chain)
import { allocate, properties } from '@nifty-oss/asset';
await allocate(umi, {
asset,
payer,
extension: properties([
{ name: 'name', value: 'nifty' },
{ name: 'version', value: 1n },
{ name: 'alpha', value: false }
]),
}).sendAndConfirm(umi);
The "type" of the property is determined by the type of the value — name is a text property; version is a number (u64) property; and alpha is a boolean property.
use nifty_asset::{
extensions::{Properties, PropertiesBuilder, ExtensionBuilder},
instructions::AllocateBuilder,
types::{ExtensionInput, ExtensionType},
};
let mut properties = PropertiesBuilder::default();
properties.add::<&str>("name", "asset");
properties.add::<u64>("version", 1);
properties.add::<bool>("alpha", false);
let ix = AllocateBuilder::new()
.asset(asset.pubkey())
.payer(Some(payer.pubkey()))
.system_program(Some(system_program::id()))
.extension(ExtensionInput {
extension_type: ExtensionType::Properties,
length: properties.len() as u32,
data: Some(properties),
})
.instruction();
use nifty_asset::{
extensions::{Properties, PropertiesBuilder, ExtensionBuilder},
instructions::AllocateBuilder,
types::{ExtensionInput, ExtensionType},
};
let mut properties = PropertiesBuilder::default();
properties.add::<&str>("name", "asset");
properties.add::<u64>("version", 1);
properties.add::<bool>("alpha", false);
AllocateCpiBuilder::new(ctx.accounts.nifty_asset_program)
.asset(ctx.accounts.group)
.payer(Some(ctx.accounts.payer))
.system_program(Some(ctx.accounts.system_program))
.extension(ExtensionInput {
extension_type: ExtensionType::Properties,
length: properties.len() as u32,
data: Some(properties),
})
.invoke();
Fetching Properties
Given an asset account, it is possible to retrieve the properties 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);
// retrieves all properties
const properties = getExtension(asset, ExtensionType.Properties);
if (properties) {
properties.values.forEach(({ name, value }) => {
console.log(name + '=' + value);
});
}
// retrieves a single property by name
const name = getProperty(assetAccount, 'name', Type.Text);
console.log('name=' + name);
use nifty_asset::{
extensions::Properties,
state::Asset,
};
let account = get_account(address)
.await
.unwrap();
let account_data = account.data.as_ref();
if let Some(properties) = Asset::get::<Properties>(account_data) {
// retrieves all properties
println!("properties: {:?}", properties);
// retrieves a single property by name
let name: &str = properties
.get::<Text>("name")
.unwrap();
}
use nifty_asset::{
extensions::Attributes,
state::Asset,
};
let data = (*ctx.accounts.asset.data).borrow();
if let Some(properties) = Asset::get::<Properties>(&data) {
// retrieves all properties
msg!("properties: {:?}", properties);
// retrieves a single property by name
let name: &str = properties
.get::<Text>("name")
.ok_or(ProgramError::InvalidAccountData)?;
}
Recall that property values are typed, so values are retrived into their original type.