Digital Assets

Overview

Digital Assets are recommended for any new collections or protocols that want to build NFTs or semi-fungible tokens.


Aptogotchi Example

Source Code

Creating a Collection

To create a digital asset, we need to create a collection first to accommodate the tokens when we first initiate the contract.


fun create_aptogotchi_collection(creator: &signer) {
let description = string::utf8(APTOGOTCHI_COLLECTION_DESCRIPTION);
let name = string::utf8(APTOGOTCHI_COLLECTION_NAME);
let uri = string::utf8(APTOGOTCHI_COLLECTION_URI);
collection::create_unlimited_collection(
creator,
description,
name,
option::none(),
uri,
);
}

We should put the function in init_module because the collection should only be created once.


public entry fun create_aptogotchi(
user: &signer,
name: String,
body: u8,
ear: u8,
face: u8,
) acquires ObjectController {
assert!(string::length(&name) <= NAME_UPPER_BOUND, error::invalid_argument(ENAME_LIMIT));
assert!(
body >= 0 && body <= BODY_MAX_VALUE,
error::invalid_argument(EBODY_VALUE_INVALID)
);
assert!(ear >= 0 && ear <= EAR_MAX_VALUE, error::invalid_argument(EEAR_VALUE_INVALID));
assert!(
face >= 0 && face <= FACE_MAX_VALUE,
error::invalid_argument(EFACE_VALUE_INVALID)
);
let uri = string::utf8(APTOGOTCHI_COLLECTION_URI);
let description = string::utf8(APTOGOTCHI_COLLECTION_DESCRIPTION);
let user_addr = address_of(user);
let token_name = to_string(&user_addr);
let parts = AptogotchiParts {
body,
ear,
face,
};
assert!(!has_aptogotchi(user_addr), error::already_exists(EUSER_ALREADY_HAS_APTOGOTCHI));
let constructor_ref = token::create_named_token(
&get_app_signer(),
string::utf8(APTOGOTCHI_COLLECTION_NAME),
description,
token_name,
option::none(),
uri,
);
let token_signer = object::generate_signer(&constructor_ref);
let mutator_ref = token::generate_mutator_ref(&constructor_ref);
let burn_ref = token::generate_burn_ref(&constructor_ref);
let transfer_ref = object::generate_transfer_ref(&constructor_ref);
// initialize/set default Aptogotchi struct values
let gotchi = Aptogotchi {
name,
birthday: timestamp::now_seconds(),
energy_points: ENERGY_UPPER_BOUND,
parts,
mutator_ref,
burn_ref,
};
move_to(&token_signer, gotchi);
// Emit event for minting Aptogotchi token
event::emit<MintAptogotchiEvent>(
MintAptogotchiEvent {
token_name,
aptogotchi_name: name,
parts,
},
);
object::transfer_with_ref(object::generate_linear_transfer_ref(&transfer_ref), address_of(user));
}


Creating a Digital Asset

A digital asset is an object with a token core.

In this example, we created a named token using token::create_named_token() with the creator information and some information about the token itself. The mutator_ref and the burn_ref can only be created using the constructor_ref when the token is created. We use those as keys to perform the mutation and burn.


#[view]
public fun get_aptogotchi_address(creator_addr: address): (address) {
let collection = string::utf8(APTOGOTCHI_COLLECTION_NAME);
let token_name = to_string(&creator_addr);
let creator_addr = get_app_signer_addr();
let token_address = token::create_token_address(
&creator_addr,
&collection,
&token_name,
);
token_address
}


How to Retrieve a Digital Asset

Since we use named token, we can always retrieve the token if we know the creator and the seed (i.e. the combination of the collection name and the token name).

In this example, we use the user address as the token name. So we can retrieve the token just through the user address. Note that this reference cannot be modified because we did not use the &mut keyword or borrow_global_mut function.


#[view]
public fun get_aptogotchi_address(creator_addr: address): (address) {
let collection = string::utf8(APTOGOTCHI_COLLECTION_NAME);
let token_name = to_string(&creator_addr);
let creator_addr = get_app_signer_addr();
let token_address = token::create_token_address(
&creator_addr,
&collection,
&token_name,
);
token_address
}



More Resources

The digital assets standard can be found here.

Link