Module 0x4::token
This defines an object-based Token. The key differentiating features from the Aptos standard token are:
- Decoupled token ownership from token data.
- Explicit data model for token metadata via adjacent resources
- Extensible framework for tokens
- Resource
Token - Resource
TokenIdentifiers - Resource
ConcurrentTokenIdentifiers - Struct
BurnRef - Struct
MutatorRef - Struct
MutationEvent - Struct
Mutation - Constants
- Function
create_common - Function
create_common_with_collection - Function
create_common_with_collection_as_owner - Function
create_common_with_collection_internal - Function
create_token - Function
create - Function
create_token_as_collection_owner - Function
create_numbered_token_object - Function
create_numbered_token - Function
create_numbered_token_as_collection_owner - Function
create_named_token_object - Function
create_named_token - Function
create_named_token_as_collection_owner - Function
create_named_token_from_seed - Function
create_named_token_from_seed_as_collection_owner - Function
create_from_account - Function
create_token_address - Function
create_token_address_with_seed - Function
create_token_seed - Function
create_token_name_with_seed - Function
generate_mutator_ref - Function
generate_burn_ref - Function
address_from_burn_ref - Function
borrow - Function
creator - Function
collection_name - Function
collection_object - Function
description - Function
name - Function
uri - Function
royalty - Function
index - Function
borrow_mut - Function
burn - Function
set_description - Function
set_name - Function
set_uri
use 0x1::aggregator_v2;
use 0x1::error;
use 0x1::event;
use 0x1::features;
use 0x1::object;
use 0x1::option;
use 0x1::signer;
use 0x1::string;
use 0x1::vector;
use 0x4::collection;
use 0x4::royalty;
Resource Token
Represents the common fields to all tokens.
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
struct Token has key
Fields
-
collection: object::Object<collection::Collection> - The collection from which this token resides.
-
index: u64 -
Deprecated in favor of
indexinside TokenIdentifiers. Was populated until concurrent_token_v2_enabled feature flag was enabled.Unique identifier within the collection, optional, 0 means unassigned
-
description: string::String - A brief description of the token.
-
name: string::String -
Deprecated in favor of
nameinside TokenIdentifiers. Was populated until concurrent_token_v2_enabled feature flag was enabled.The name of the token, which should be unique within the collection; the length of name should be smaller than 128, characters, eg: “Aptos Animal #1234”
-
uri: string::String - The Uniform Resource Identifier (uri) pointing to the JSON file stored in off-chain storage; the URL length will likely need a maximum any suggestions?
-
mutation_events: event::EventHandle<token::MutationEvent> - Emitted upon any mutation of the token.
Resource TokenIdentifiers
Represents first addition to the common fields for all tokens Started being populated once aggregator_v2_api_enabled was enabled.
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
struct TokenIdentifiers has key
Fields
-
index: aggregator_v2::AggregatorSnapshot<u64> - Unique identifier within the collection, optional, 0 means unassigned
-
name: aggregator_v2::DerivedStringSnapshot - The name of the token, which should be unique within the collection; the length of name should be smaller than 128, characters, eg: "Aptos Animal #1234"
Resource ConcurrentTokenIdentifiers
#[resource_group_member(#[group = 0x1::object::ObjectGroup])]
#[deprecated]
struct ConcurrentTokenIdentifiers has key
Fields
-
index: aggregator_v2::AggregatorSnapshot<u64> -
name: aggregator_v2::AggregatorSnapshot<string::String>
Struct BurnRef
This enables burning an NFT, if possible, it will also delete the object. Note, the data in inner and self occupies 32-bytes each, rather than have both, this data structure makes a small optimization to support either and take a fixed amount of 34-bytes.
struct BurnRef has drop, store
Fields
-
inner: option::Option<object::DeleteRef> -
self: option::Option<address>
Struct MutatorRef
This enables mutating description and URI by higher level services.
struct MutatorRef has drop, store
Fields
-
self: address
Struct MutationEvent
Contains the mutated fields name. This makes the life of indexers easier, so that they can directly understand the behavior in a writeset.
struct MutationEvent has drop, store
Fields
-
mutated_field_name: string::String -
old_value: string::String -
new_value: string::String
Struct Mutation
#[event]
struct Mutation has drop, store
Fields
-
token_address: address -
mutated_field_name: string::String -
old_value: string::String -
new_value: string::String
Constants
The URI is over the maximum length
const EURI_TOO_LONG: u64 = 5;
const MAX_URI_LENGTH: u64 = 512;
The calling signer is not the owner
const ENOT_OWNER: u64 = 8;
The collection owner feature is not supported
const ECOLLECTION_OWNER_NOT_SUPPORTED: u64 = 9;
The description is over the maximum length
const EDESCRIPTION_TOO_LONG: u64 = 6;
const MAX_DESCRIPTION_LENGTH: u64 = 2048;
The field being changed is not mutable
const EFIELD_NOT_MUTABLE: u64 = 3;
The provided signer is not the creator
const ENOT_CREATOR: u64 = 2;
The seed is over the maximum length
const ESEED_TOO_LONG: u64 = 7;
The token does not exist
const ETOKEN_DOES_NOT_EXIST: u64 = 1;
The token name is over the maximum length
const ETOKEN_NAME_TOO_LONG: u64 = 4;
const MAX_TOKEN_NAME_LENGTH: u64 = 128;
const MAX_TOKEN_SEED_LENGTH: u64 = 128;
Function create_common
fun create_common(creator: &signer, constructor_ref: &object::ConstructorRef, collection_name: string::String, description: string::String, name_prefix: string::String, name_with_index_suffix: option::Option<string::String>, royalty: option::Option<royalty::Royalty>, uri: string::String)
Implementation
inline fun create_common(
creator: &signer,
constructor_ref: &ConstructorRef,
collection_name: String,
description: String,
name_prefix: String,
// If option::some, numbered token is created - i.e. index is appended to the name.
// If option::none, name_prefix is the full name of the token.
name_with_index_suffix: Option<String>,
royalty: Option<Royalty>,
uri: String,
) {
let creator_address = signer::address_of(creator);
let collection_addr = collection::create_collection_address(&creator_address, &collection_name);
let collection = object::address_to_object<Collection>(collection_addr);
create_common_with_collection(
creator,
constructor_ref,
collection,
description,
name_prefix,
name_with_index_suffix,
royalty,
uri
)
}
Function create_common_with_collection
fun create_common_with_collection(creator: &signer, constructor_ref: &object::ConstructorRef, collection: object::Object<collection::Collection>, description: string::String, name_prefix: string::String, name_with_index_suffix: option::Option<string::String>, royalty: option::Option<royalty::Royalty>, uri: string::String)
Implementation
inline fun create_common_with_collection(
creator: &signer,
constructor_ref: &ConstructorRef,
collection: Object<Collection>,
description: String,
name_prefix: String,
// If option::some, numbered token is created - i.e. index is appended to the name.
// If option::none, name_prefix is the full name of the token.
name_with_index_suffix: Option<String>,
royalty: Option<Royalty>,
uri: String,
) {
assert!(collection::creator(collection) == signer::address_of(creator), error::unauthenticated(ENOT_CREATOR));
create_common_with_collection_internal(
constructor_ref,
collection,
description,
name_prefix,
name_with_index_suffix,
royalty,
uri
);
}
Function create_common_with_collection_as_owner
fun create_common_with_collection_as_owner(owner: &signer, constructor_ref: &object::ConstructorRef, collection: object::Object<collection::Collection>, description: string::String, name_prefix: string::String, name_with_index_suffix: option::Option<string::String>, royalty: option::Option<royalty::Royalty>, uri: string::String)
Implementation
inline fun create_common_with_collection_as_owner(
owner: &signer,
constructor_ref: &ConstructorRef,
collection: Object<Collection>,
description: String,
name_prefix: String,
// If option::some, numbered token is created - i.e. index is appended to the name.
// If option::none, name_prefix is the full name of the token.
name_with_index_suffix: Option<String>,
royalty: Option<Royalty>,
uri: String,
) {
assert!(features::is_collection_owner_enabled(), error::unavailable(ECOLLECTION_OWNER_NOT_SUPPORTED));
assert!(collection.owner() == signer::address_of(owner), error::unauthenticated(ENOT_OWNER));
create_common_with_collection_internal(
constructor_ref,
collection,
description,
name_prefix,
name_with_index_suffix,
royalty,
uri
);
}
Function create_common_with_collection_internal
fun create_common_with_collection_internal(constructor_ref: &object::ConstructorRef, collection: object::Object<collection::Collection>, description: string::String, name_prefix: string::String, name_with_index_suffix: option::Option<string::String>, royalty: option::Option<royalty::Royalty>, uri: string::String)
Implementation
inline fun create_common_with_collection_internal(
constructor_ref: &ConstructorRef,
collection: Object<Collection>,
description: String,
name_prefix: String,
// If option::some, numbered token is created - i.e. index is appended to the name.
// If option::none, name_prefix is the full name of the token.
name_with_index_suffix: Option<String>,
royalty: Option<Royalty>,
uri: String,
) {
if (name_with_index_suffix.is_some()) {
// Be conservative, as we don't know what length the index will be, and assume worst case (20 chars in MAX_U64)
assert!(
name_prefix.length() + 20 + name_with_index_suffix.borrow().length() <= MAX_TOKEN_NAME_LENGTH,
error::out_of_range(ETOKEN_NAME_TOO_LONG)
);
} else {
assert!(name_prefix.length() <= MAX_TOKEN_NAME_LENGTH, error::out_of_range(ETOKEN_NAME_TOO_LONG));
};
assert!(description.length() <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
assert!(uri.length() <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
let object_signer = constructor_ref.generate_signer();
let index = collection::increment_supply(&collection, signer::address_of(&object_signer)).destroy_with_default(
aggregator_v2::create_snapshot<u64>(0)
);
// If create_numbered_token called us, add index to the name.
let name = if (name_with_index_suffix.is_some()) {
aggregator_v2::derive_string_concat(name_prefix, &index, name_with_index_suffix.extract())
} else {
aggregator_v2::create_derived_string(name_prefix)
};
let deprecated_index = 0;
let deprecated_name = string::utf8(b"");
let token_concurrent = TokenIdentifiers {
index,
name,
};
move_to(&object_signer, token_concurrent);
let token = Token {
collection,
index: deprecated_index,
description,
name: deprecated_name,
uri,
mutation_events: object::new_event_handle(&object_signer),
};
move_to(&object_signer, token);
if (royalty.is_some()) {
royalty::init(constructor_ref, royalty.extract())
};
}
Function create_token
Creates a new token object with a unique address and returns the ConstructorRef for additional specialization. This takes in the collection object instead of the collection name. This function must be called if the collection name has been previously changed.
public fun create_token(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_token(
creator: &signer,
collection: Object<Collection>,
description: String,
name: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let creator_address = signer::address_of(creator);
let constructor_ref = object::create_object(creator_address);
create_common_with_collection(
creator,
&constructor_ref,
collection,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create
Creates a new token object with a unique address and returns the ConstructorRef for additional specialization.
public fun create(creator: &signer, collection_name: string::String, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create(
creator: &signer,
collection_name: String,
description: String,
name: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let creator_address = signer::address_of(creator);
let constructor_ref = object::create_object(creator_address);
create_common(
creator,
&constructor_ref,
collection_name,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create_token_as_collection_owner
Same functionality as create_token, but the token can only be created by the collection owner.
public fun create_token_as_collection_owner(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_token_as_collection_owner(
creator: &signer,
collection: Object<Collection>,
description: String,
name: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let creator_address = signer::address_of(creator);
let constructor_ref = object::create_object(creator_address);
create_common_with_collection_as_owner(
creator,
&constructor_ref,
collection,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create_numbered_token_object
Creates a new token object with a unique address and returns the ConstructorRef for additional specialization. The name is created by concatenating the (name_prefix, index, name_suffix). This function allows creating tokens in parallel, from the same collection, while providing sequential names.
This takes in the collection object instead of the collection name. This function must be called if the collection name has been previously changed.
public fun create_numbered_token_object(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name_with_index_prefix: string::String, name_with_index_suffix: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_numbered_token_object(
creator: &signer,
collection: Object<Collection>,
description: String,
name_with_index_prefix: String,
name_with_index_suffix: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let creator_address = signer::address_of(creator);
let constructor_ref = object::create_object(creator_address);
create_common_with_collection(
creator,
&constructor_ref,
collection,
description,
name_with_index_prefix,
option::some(name_with_index_suffix),
royalty,
uri
);
constructor_ref
}
Function create_numbered_token
Creates a new token object with a unique address and returns the ConstructorRef for additional specialization. The name is created by concatenating the (name_prefix, index, name_suffix). This function will allow creating tokens in parallel, from the same collection, while providing sequential names.
public fun create_numbered_token(creator: &signer, collection_name: string::String, description: string::String, name_with_index_prefix: string::String, name_with_index_suffix: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_numbered_token(
creator: &signer,
collection_name: String,
description: String,
name_with_index_prefix: String,
name_with_index_suffix: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let creator_address = signer::address_of(creator);
let constructor_ref = object::create_object(creator_address);
create_common(
creator,
&constructor_ref,
collection_name,
description,
name_with_index_prefix,
option::some(name_with_index_suffix),
royalty,
uri
);
constructor_ref
}
Function create_numbered_token_as_collection_owner
Same functionality as create_numbered_token_object, but the token can only be created by the collection owner.
public fun create_numbered_token_as_collection_owner(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name_with_index_prefix: string::String, name_with_index_suffix: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_numbered_token_as_collection_owner(
creator: &signer,
collection: Object<Collection>,
description: String,
name_with_index_prefix: String,
name_with_index_suffix: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let creator_address = signer::address_of(creator);
let constructor_ref = object::create_object(creator_address);
create_common_with_collection_as_owner(
creator,
&constructor_ref,
collection,
description,
name_with_index_prefix,
option::some(name_with_index_suffix),
royalty,
uri
);
constructor_ref
}
Function create_named_token_object
Creates a new token object from a token name and returns the ConstructorRef for additional specialization. This function must be called if the collection name has been previously changed.
public fun create_named_token_object(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_named_token_object(
creator: &signer,
collection: Object<Collection>,
description: String,
name: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let seed = create_token_seed(&collection::name(collection), &name);
let constructor_ref = object::create_named_object(creator, seed);
create_common_with_collection(
creator,
&constructor_ref,
collection,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create_named_token
Creates a new token object from a token name and returns the ConstructorRef for additional specialization.
public fun create_named_token(creator: &signer, collection_name: string::String, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_named_token(
creator: &signer,
collection_name: String,
description: String,
name: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let seed = create_token_seed(&collection_name, &name);
let constructor_ref = object::create_named_object(creator, seed);
create_common(
creator,
&constructor_ref,
collection_name,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create_named_token_as_collection_owner
Same functionality as create_named_token_object, but the token can only be created by the collection owner.
public fun create_named_token_as_collection_owner(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_named_token_as_collection_owner(
creator: &signer,
collection: Object<Collection>,
description: String,
name: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let seed = create_token_seed(&collection::name(collection), &name);
let constructor_ref = object::create_named_object(creator, seed);
create_common_with_collection_as_owner(
creator,
&constructor_ref,
collection,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create_named_token_from_seed
Creates a new token object from a token name and seed. Returns the ConstructorRef for additional specialization. This function must be called if the collection name has been previously changed.
public fun create_named_token_from_seed(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name: string::String, seed: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_named_token_from_seed(
creator: &signer,
collection: Object<Collection>,
description: String,
name: String,
seed: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let seed = create_token_name_with_seed(&collection::name(collection), &name, &seed);
let constructor_ref = object::create_named_object(creator, seed);
create_common_with_collection(creator, &constructor_ref, collection, description, name, option::none(), royalty, uri);
constructor_ref
}
Function create_named_token_from_seed_as_collection_owner
Same functionality as create_named_token_from_seed, but the token can only be created by the collection owner.
public fun create_named_token_from_seed_as_collection_owner(creator: &signer, collection: object::Object<collection::Collection>, description: string::String, name: string::String, seed: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_named_token_from_seed_as_collection_owner(
creator: &signer,
collection: Object<Collection>,
description: String,
name: String,
seed: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let seed = create_token_name_with_seed(&collection::name(collection), &name, &seed);
let constructor_ref = object::create_named_object(creator, seed);
create_common_with_collection_as_owner(
creator,
&constructor_ref,
collection,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create_from_account
DEPRECATED: Use create instead for identical behavior.
Creates a new token object from an account GUID and returns the ConstructorRef for additional specialization.
#[deprecated]
public fun create_from_account(creator: &signer, collection_name: string::String, description: string::String, name: string::String, royalty: option::Option<royalty::Royalty>, uri: string::String): object::ConstructorRef
Implementation
public fun create_from_account(
creator: &signer,
collection_name: String,
description: String,
name: String,
royalty: Option<Royalty>,
uri: String,
): ConstructorRef {
let constructor_ref = object::create_object_from_account(creator);
create_common(
creator,
&constructor_ref,
collection_name,
description,
name,
option::none(),
royalty,
uri
);
constructor_ref
}
Function create_token_address
Generates the token’s address based upon the creator’s address, the collection’s name and the token’s name.
public fun create_token_address(creator: &address, collection: &string::String, name: &string::String): address
Implementation
public fun create_token_address(creator: &address, collection: &String, name: &String): address {
object::create_object_address(creator, create_token_seed(collection, name))
}
Function create_token_address_with_seed
Generates the token’s address based upon the creator’s address, the collection object and the token’s name and seed.
#[view]
public fun create_token_address_with_seed(creator: address, collection: string::String, name: string::String, seed: string::String): address
Implementation
public fun create_token_address_with_seed(creator: address, collection: String, name: String, seed: String): address {
let seed = create_token_name_with_seed(&collection, &name, &seed);
object::create_object_address(&creator, seed)
}
Function create_token_seed
Named objects are derived from a seed, the token’s seed is its name appended to the collection’s name.
public fun create_token_seed(collection: &string::String, name: &string::String): vector<u8>
Implementation
public fun create_token_seed(collection: &String, name: &String): vector<u8> {
assert!(name.length() <= MAX_TOKEN_NAME_LENGTH, error::out_of_range(ETOKEN_NAME_TOO_LONG));
let seed = *collection.bytes();
seed.append(b"::");
seed.append(*name.bytes());
seed
}
Function create_token_name_with_seed
public fun create_token_name_with_seed(collection: &string::String, name: &string::String, seed: &string::String): vector<u8>
Implementation
public fun create_token_name_with_seed(collection: &String, name: &String, seed: &String): vector<u8> {
assert!(seed.length() <= MAX_TOKEN_SEED_LENGTH, error::out_of_range(ESEED_TOO_LONG));
let seeds = create_token_seed(collection, name);
seeds.append(*seed.bytes());
seeds
}
Function generate_mutator_ref
Creates a MutatorRef, which gates the ability to mutate any fields that support mutation.
public fun generate_mutator_ref(ref: &object::ConstructorRef): token::MutatorRef
Implementation
public fun generate_mutator_ref(ref: &ConstructorRef): MutatorRef {
let object = ref.object_from_constructor_ref<Token>();
MutatorRef { self: object.object_address() }
}
Function generate_burn_ref
Creates a BurnRef, which gates the ability to burn the given token.
public fun generate_burn_ref(ref: &object::ConstructorRef): token::BurnRef
Implementation
public fun generate_burn_ref(ref: &ConstructorRef): BurnRef {
let (inner, self) = if (ref.can_generate_delete_ref()) {
let delete_ref = ref.generate_delete_ref();
(option::some(delete_ref), option::none())
} else {
let addr = ref.address_from_constructor_ref();
(option::none(), option::some(addr))
};
BurnRef { self, inner }
}
Function address_from_burn_ref
Extracts the tokens address from a BurnRef.
public fun address_from_burn_ref(ref: &token::BurnRef): address
Implementation
public fun address_from_burn_ref(ref: &BurnRef): address {
if (ref.inner.is_some()) {
ref.inner.borrow().address_from_delete_ref()
} else {
*ref.self.borrow()
}
}
Function borrow
fun borrow<T: key>(token: &object::Object<T>): &token::Token
Implementation
inline fun borrow<T: key>(token: &Object<T>): &Token {
let token_address = token.object_address();
assert!(
exists<Token>(token_address),
error::not_found(ETOKEN_DOES_NOT_EXIST),
);
&Token[token_address]
}
Function creator
#[view]
public fun creator<T: key>(token: object::Object<T>): address
Implementation
public fun creator<T: key>(token: Object<T>): address acquires Token {
collection::creator(borrow(&token).collection)
}
Function collection_name
#[view]
public fun collection_name<T: key>(token: object::Object<T>): string::String
Implementation
public fun collection_name<T: key>(token: Object<T>): String acquires Token {
collection::name(borrow(&token).collection)
}
Function collection_object
#[view]
public fun collection_object<T: key>(token: object::Object<T>): object::Object<collection::Collection>
Implementation
public fun collection_object<T: key>(token: Object<T>): Object<Collection> acquires Token {
borrow(&token).collection
}
Function description
#[view]
public fun description<T: key>(token: object::Object<T>): string::String
Implementation
public fun description<T: key>(token: Object<T>): String acquires Token {
borrow(&token).description
}
Function name
Avoid this method in the same transaction as the token is minted as that would prohibit transactions to be executed in parallel.
#[view]
public fun name<T: key>(token: object::Object<T>): string::String
Implementation
public fun name<T: key>(token: Object<T>): String acquires Token, TokenIdentifiers {
let token_address = token.object_address();
if (exists<TokenIdentifiers>(token_address)) {
TokenIdentifiers[token_address].name.read_derived_string()
} else {
borrow(&token).name
}
}
Function uri
#[view]
public fun uri<T: key>(token: object::Object<T>): string::String
Implementation
public fun uri<T: key>(token: Object<T>): String acquires Token {
borrow(&token).uri
}
Function royalty
#[view]
public fun royalty<T: key>(token: object::Object<T>): option::Option<royalty::Royalty>
Implementation
public fun royalty<T: key>(token: Object<T>): Option<Royalty> acquires Token {
borrow(&token);
let royalty = royalty::get(token);
if (royalty.is_some()) {
royalty
} else {
let creator = creator(token);
let collection_name = collection_name(token);
let collection_address = collection::create_collection_address(&creator, &collection_name);
let collection = object::address_to_object<collection::Collection>(collection_address);
royalty::get(collection)
}
}
Function index
Avoid this method in the same transaction as the token is minted as that would prohibit transactions to be executed in parallel.
#[view]
public fun index<T: key>(token: object::Object<T>): u64
Implementation
public fun index<T: key>(token: Object<T>): u64 acquires Token, TokenIdentifiers {
let token_address = token.object_address();
if (exists<TokenIdentifiers>(token_address)) {
TokenIdentifiers[token_address].index.read_snapshot()
} else {
borrow(&token).index
}
}
Function borrow_mut
fun borrow_mut(mutator_ref: &token::MutatorRef): &mut token::Token
Implementation
inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Token {
assert!(
exists<Token>(mutator_ref.self),
error::not_found(ETOKEN_DOES_NOT_EXIST),
);
&mut Token[mutator_ref.self]
}
Function burn
public fun burn(burn_ref: token::BurnRef)
Implementation
public fun burn(burn_ref: BurnRef) acquires Token, TokenIdentifiers {
let (addr, previous_owner) = if (burn_ref.inner.is_some()) {
let delete_ref = burn_ref.inner.extract();
let addr = delete_ref.address_from_delete_ref();
let previous_owner = object::address_to_object<Token>(addr).owner();
delete_ref.delete();
(addr, previous_owner)
} else {
let addr = burn_ref.self.extract();
let previous_owner = object::address_to_object<Token>(addr).owner();
(addr, previous_owner)
};
if (royalty::exists_at(addr)) {
royalty::delete(addr)
};
let Token {
collection,
index: deprecated_index,
description: _,
name: _,
uri: _,
mutation_events,
} = move_from<Token>(addr);
let index = if (exists<TokenIdentifiers>(addr)) {
let TokenIdentifiers {
index,
name: _,
} = move_from<TokenIdentifiers>(addr);
index.read_snapshot()
} else {
deprecated_index
};
event::destroy_handle(mutation_events);
collection::decrement_supply(&collection, addr, option::some(index), previous_owner);
}
Function set_description
public fun set_description(mutator_ref: &token::MutatorRef, description: string::String)
Implementation
public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Token {
assert!(description.length() <= MAX_DESCRIPTION_LENGTH, error::out_of_range(EDESCRIPTION_TOO_LONG));
let token = borrow_mut(mutator_ref);
event::emit(Mutation {
token_address: mutator_ref.self,
mutated_field_name: string::utf8(b"description"),
old_value: token.description,
new_value: description
});
token.description = description;
}
Function set_name
public fun set_name(mutator_ref: &token::MutatorRef, name: string::String)
Implementation
public fun set_name(mutator_ref: &MutatorRef, name: String) acquires Token, TokenIdentifiers {
assert!(name.length() <= MAX_TOKEN_NAME_LENGTH, error::out_of_range(ETOKEN_NAME_TOO_LONG));
let token = borrow_mut(mutator_ref);
let old_name = if (exists<TokenIdentifiers>(mutator_ref.self)) {
let token_concurrent = &mut TokenIdentifiers[mutator_ref.self];
let old_name = token_concurrent.name.read_derived_string();
token_concurrent.name = aggregator_v2::create_derived_string(name);
old_name
} else {
let old_name = token.name;
token.name = name;
old_name
};
event::emit(Mutation {
token_address: mutator_ref.self,
mutated_field_name: string::utf8(b"name"),
old_value: old_name,
new_value: name
});
}
Function set_uri
public fun set_uri(mutator_ref: &token::MutatorRef, uri: string::String)
Implementation
public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Token {
assert!(uri.length() <= MAX_URI_LENGTH, error::out_of_range(EURI_TOO_LONG));
let token = borrow_mut(mutator_ref);
event::emit(Mutation {
token_address: mutator_ref.self,
mutated_field_name: string::utf8(b"uri"),
old_value: token.uri,
new_value: uri,
});
token.uri = uri;
}