Skip to content

token - [mainnet]

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
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;

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;

Structs

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>

MutatorRef

This enables mutating description and URI by higher level services.

struct MutatorRef has drop, store
Fields
self: address

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

Mutation

#[event]
struct Mutation has drop, store
Fields
token_address: address
mutated_field_name: string::String
old_value: string::String
new_value: string::String

Resources

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 index inside 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 name inside 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.

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"

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>

Functions

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
)
}

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
);
}

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!(object::owner(collection) == 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
);
}

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 = object::generate_signer(constructor_ref);
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())
};
}

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
}

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
}

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
}

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
}

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
}

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
}

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
}

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
}

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
}

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
}

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
}

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
}

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))
}

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)
}

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
}

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
}

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 = object::object_from_constructor_ref<Token>(ref);
MutatorRef { self: object::object_address(&object) }
}

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 (object::can_generate_delete_ref(ref)) {
let delete_ref = object::generate_delete_ref(ref);
(option::some(delete_ref), option::none())
} else {
let addr = object::address_from_constructor_ref(ref);
(option::none(), option::some(addr))
};
BurnRef { self, inner }
}

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()) {
object::address_from_delete_ref(ref.inner.borrow())
} else {
*ref.self.borrow()
}
}

borrow

fun borrow<T: key>(token: &object::Object<T>): &token::Token
Implementation
inline fun borrow<T: key>(token: &Object<T>): &Token acquires Token {
let token_address = object::object_address(token);
assert!(
exists<Token>(token_address),
error::not_found(ETOKEN_DOES_NOT_EXIST),
);
&Token[token_address]
}

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)
}

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)
}

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
}

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
}

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 = object::object_address(&token);
if (exists<TokenIdentifiers>(token_address)) {
aggregator_v2::read_derived_string(&TokenIdentifiers[token_address].name)
} else {
borrow(&token).name
}
}

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
}

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)
}
}

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 = object::object_address(&token);
if (exists<TokenIdentifiers>(token_address)) {
aggregator_v2::read_snapshot(&TokenIdentifiers[token_address].index)
} else {
borrow(&token).index
}
}

borrow_mut

fun borrow_mut(mutator_ref: &token::MutatorRef): &mut token::Token
Implementation
inline fun borrow_mut(mutator_ref: &MutatorRef): &mut Token acquires Token {
assert!(
exists<Token>(mutator_ref.self),
error::not_found(ETOKEN_DOES_NOT_EXIST),
);
&mut Token[mutator_ref.self]
}

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 = object::address_from_delete_ref(&delete_ref);
let previous_owner = object::owner(object::address_to_object<Token>(addr));
object::delete(delete_ref);
(addr, previous_owner)
} else {
let addr = burn_ref.self.extract();
let previous_owner = object::owner(object::address_to_object<Token>(addr));
(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);
aggregator_v2::read_snapshot(&index)
} else {
deprecated_index
};
event::destroy_handle(mutation_events);
collection::decrement_supply(&collection, addr, option::some(index), previous_owner);
}

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);
if (std::features::module_event_migration_enabled()) {
event::emit(Mutation {
token_address: mutator_ref.self,
mutated_field_name: string::utf8(b"description"),
old_value: token.description,
new_value: description
})
} else {
event::emit_event(
&mut token.mutation_events,
MutationEvent {
mutated_field_name: string::utf8(b"description"),
old_value: token.description,
new_value: description
},
);
};
token.description = description;
}

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 = aggregator_v2::read_derived_string(&token_concurrent.name);
token_concurrent.name = aggregator_v2::create_derived_string(name);
old_name
} else {
let old_name = token.name;
token.name = name;
old_name
};
if (std::features::module_event_migration_enabled()) {
event::emit(Mutation {
token_address: mutator_ref.self,
mutated_field_name: string::utf8(b"name"),
old_value: old_name,
new_value: name
})
} else {
event::emit_event(
&mut token.mutation_events,
MutationEvent {
mutated_field_name: string::utf8(b"name"),
old_value: old_name,
new_value: name
},
);
};
}

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);
if (std::features::module_event_migration_enabled()) {
event::emit(Mutation {
token_address: mutator_ref.self,
mutated_field_name: string::utf8(b"uri"),
old_value: token.uri,
new_value: uri,
})
} else {
event::emit_event(
&mut token.mutation_events,
MutationEvent {
mutated_field_name: string::utf8(b"uri"),
old_value: token.uri,
new_value: uri,
},
);
};
token.uri = uri;
}