diff --git a/api/src/tests/objects.rs b/api/src/tests/objects.rs index 8caae930b669d..74e589f1e5070 100644 --- a/api/src/tests/objects.rs +++ b/api/src/tests/objects.rs @@ -37,7 +37,7 @@ async fn test_gen_object() { let collection_addr = account_address::create_collection_address(user_addr, "Hero Quest!"); let token_addr = account_address::create_token_address(user_addr, "Hero Quest!", "Wukong"); let object_resource = "0x1::object::ObjectCore"; - let token_resource = format!("0x{}::token::Token", user_addr); + let token_resource = "0x4::token::Token"; let hero_resource = format!("0x{}::hero::Hero", user_addr); let collection0 = context.gen_all_resources(&collection_addr).await; @@ -56,7 +56,7 @@ async fn test_gen_object() { let hero = context.gen_all_resources(&token_addr).await; let hero_map = to_object(hero); assert!(hero_map.contains_key(object_resource)); - assert!(hero_map.contains_key(&token_resource)); + assert!(hero_map.contains_key(token_resource)); assert!(hero_map.contains_key(&hero_resource)); let owner: AccountAddress = hero_map[object_resource]["owner"] .as_str() diff --git a/aptos-move/aptos-release-builder/data/release.yaml b/aptos-move/aptos-release-builder/data/release.yaml index cd956ac7baf75..4b0112c574ede 100644 --- a/aptos-move/aptos-release-builder/data/release.yaml +++ b/aptos-move/aptos-release-builder/data/release.yaml @@ -20,6 +20,7 @@ update_sequence: - multisig_accounts - delegation_pools - ed25519_pubkey_validate_return_false_wrong_length + - struct_constructors disabled: [] - Consensus: V1: diff --git a/aptos-move/aptos-release-builder/src/components/framework.rs b/aptos-move/aptos-release-builder/src/components/framework.rs index e923005c08b0f..81d721d78c7e9 100644 --- a/aptos-move/aptos-release-builder/src/components/framework.rs +++ b/aptos-move/aptos-release-builder/src/components/framework.rs @@ -30,6 +30,7 @@ pub fn generate_upgrade_proposals( ("0x1", "aptos-move/framework/aptos-stdlib"), ("0x1", "aptos-move/framework/aptos-framework"), ("0x3", "aptos-move/framework/aptos-token"), + ("0x4", "aptos-move/framework/aptos-token-objects"), ]; let mut result: Vec<(String, String)> = vec![]; diff --git a/aptos-move/e2e-move-tests/src/harness.rs b/aptos-move/e2e-move-tests/src/harness.rs index 42cb2009fb2a4..c17e42f9b58c8 100644 --- a/aptos-move/e2e-move-tests/src/harness.rs +++ b/aptos-move/e2e-move-tests/src/harness.rs @@ -615,3 +615,18 @@ macro_rules! assert_vm_status { ); }}; } + +#[macro_export] +macro_rules! assert_move_abort { + ($s:expr, $c:ident) => {{ + use aptos_types::transaction::*; + assert!(match $s { + TransactionStatus::Keep(ExecutionStatus::MoveAbort { + location: _, + code: _, + info, + }) => info == $c, + _ => false, + }); + }}; +} diff --git a/aptos-move/e2e-move-tests/src/tests/string_args.rs b/aptos-move/e2e-move-tests/src/tests/string_args.rs index e7d7b15177b32..0910f2cf82aec 100644 --- a/aptos-move/e2e-move-tests/src/tests/string_args.rs +++ b/aptos-move/e2e-move-tests/src/tests/string_args.rs @@ -1,8 +1,11 @@ // Copyright © Aptos Foundation // SPDX-License-Identifier: Apache-2.0 -use crate::{assert_success, assert_vm_status, tests::common, MoveHarness}; -use aptos_types::account_address::AccountAddress; +use crate::{assert_move_abort, assert_success, assert_vm_status, tests::common, MoveHarness}; +use aptos_types::{ + account_address::AccountAddress, + transaction::{AbortInfo, TransactionStatus}, +}; use move_core_types::{ identifier::Identifier, language_storage::{StructTag, TypeTag}, @@ -62,11 +65,27 @@ fn success_generic(ty_args: Vec<TypeTag>, tests: Vec<(&str, Vec<(Vec<Vec<u8>>, & } } -fn fail(tests: Vec<(&str, Vec<Vec<u8>>, StatusCode)>) { +fn deserialization_failure() -> impl Fn(TransactionStatus) { + let status_code = StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT; + move |txn_status| assert_vm_status!(txn_status, status_code) +} + +fn abort_info() -> impl Fn(TransactionStatus) { + let abort_info = Some(AbortInfo { + reason_name: "EINVALID_UTF8".to_string(), + description: "An invalid UTF8 encoding.".to_string(), + }); + move |txn_status| assert_move_abort!(txn_status, abort_info) +} + +fn fail(tests: Vec<(&str, Vec<Vec<u8>>, impl Fn(TransactionStatus))>) { fail_generic(vec![], tests) } -fn fail_generic(ty_args: Vec<TypeTag>, tests: Vec<(&str, Vec<Vec<u8>>, StatusCode)>) { +fn fail_generic( + ty_args: Vec<TypeTag>, + tests: Vec<(&str, Vec<Vec<u8>>, impl Fn(TransactionStatus))>, +) { let mut h = MoveHarness::new(); // Load the code @@ -81,7 +100,7 @@ fn fail_generic(ty_args: Vec<TypeTag>, tests: Vec<(&str, Vec<Vec<u8>>, StatusCod for (entry, args, err) in tests { // Now send hi transaction, after that resource should exist and carry value let status = h.run_entry_function(&acc, str::parse(entry).unwrap(), ty_args.clone(), args); - assert_vm_status!(status, err); + err(status); } } @@ -289,38 +308,22 @@ fn string_args_bad_utf8() { // simple strings let args = vec![bcs::to_bytes(&vec![0xF0u8, 0x28u8, 0x8Cu8, 0xBCu8]).unwrap()]; - tests.push(( - "0xcafe::test::hi", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::hi", args, abort_info())); let args = vec![bcs::to_bytes(&vec![0xC3u8, 0x28u8]).unwrap()]; - tests.push(( - "0xcafe::test::hi", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::hi", args, abort_info())); // vector of strings let bad = vec![0xC3u8, 0x28u8]; let s_vec = vec![&bad[..], "hello".as_bytes(), "world".as_bytes()]; let i = 0u64; let args = vec![bcs::to_bytes(&s_vec).unwrap(), bcs::to_bytes(&i).unwrap()]; - tests.push(( - "0xcafe::test::str_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec", args, abort_info())); let bad = vec![0xC3u8, 0x28u8]; let s_vec = vec![&bad[..], "hello".as_bytes(), "world".as_bytes()]; let args = vec![bcs::to_bytes(&s_vec).unwrap(), bcs::to_bytes(&i).unwrap()]; - tests.push(( - "0xcafe::test::str_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec", args, abort_info())); // vector of vector of strings let i = 0u64; @@ -345,11 +348,7 @@ fn string_args_bad_utf8() { bcs::to_bytes(&i).unwrap(), bcs::to_bytes(&j).unwrap(), ]; - tests.push(( - "0xcafe::test::str_vec_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec_vec", args, abort_info())); let bad = vec![0xF0u8, 0x28u8, 0x8Cu8, 0x28u8]; let s_vec = vec![ @@ -370,11 +369,7 @@ fn string_args_bad_utf8() { bcs::to_bytes(&i).unwrap(), bcs::to_bytes(&j).unwrap(), ]; - tests.push(( - "0xcafe::test::str_vec_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec_vec", args, abort_info())); let bad = vec![0x60u8, 0xFFu8]; let s_vec = vec![ @@ -395,11 +390,7 @@ fn string_args_bad_utf8() { bcs::to_bytes(&i).unwrap(), bcs::to_bytes(&j).unwrap(), ]; - tests.push(( - "0xcafe::test::str_vec_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec_vec", args, abort_info())); fail(tests); } @@ -421,7 +412,7 @@ fn string_args_chopped() { fail(vec![( "0xcafe::test::str_vec", args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, + deserialization_failure(), )]); i /= 2; } @@ -437,20 +428,12 @@ fn string_args_bad_length() { // length over max size let mut args = bcs::to_bytes(&vec![0x30u8; 100000]).unwrap(); args.truncate(20); - tests.push(( - "0xcafe::test::hi", - vec![args], - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::hi", vec![args], deserialization_failure())); // length in size but input chopped let mut args = bcs::to_bytes(&vec![0x30u8; 30000]).unwrap(); args.truncate(300); - tests.push(( - "0xcafe::test::hi", - vec![args], - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::hi", vec![args], deserialization_failure())); // vector of strings @@ -461,11 +444,7 @@ fn string_args_bad_length() { bcs_vec.truncate(200); let i = 0u64; let args = vec![bcs_vec, bcs::to_bytes(&i).unwrap()]; - tests.push(( - "0xcafe::test::str_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec", args, deserialization_failure())); // length over max size after 2 big-ish strings let bad = vec![0x30u8; 100000]; @@ -474,11 +453,7 @@ fn string_args_bad_length() { let mut bcs_vec = bcs::to_bytes(&s_vec).unwrap(); bcs_vec.truncate(30000); let args = vec![bcs_vec, bcs::to_bytes(&i).unwrap()]; - tests.push(( - "0xcafe::test::str_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec", args, deserialization_failure())); // length in size but input chopped let big = vec![0x30u8; 10000]; @@ -486,11 +461,7 @@ fn string_args_bad_length() { let mut bcs_vec = bcs::to_bytes(&s_vec).unwrap(); bcs_vec.truncate(20000); let args = vec![bcs_vec, bcs::to_bytes(&i).unwrap()]; - tests.push(( - "0xcafe::test::str_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec", args, deserialization_failure())); // vector of vector of strings @@ -518,11 +489,7 @@ fn string_args_bad_length() { bcs::to_bytes(&i).unwrap(), bcs::to_bytes(&j).unwrap(), ]; - tests.push(( - "0xcafe::test::str_vec_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec_vec", args, deserialization_failure())); let bad = vec![0x30u8; 10000]; let s_vec = vec![ @@ -545,11 +512,7 @@ fn string_args_bad_length() { bcs::to_bytes(&i).unwrap(), bcs::to_bytes(&j).unwrap(), ]; - tests.push(( - "0xcafe::test::str_vec_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec_vec", args, deserialization_failure())); let bad = vec![0x30u8; 100000]; let s_vec = vec![ @@ -572,11 +535,7 @@ fn string_args_bad_length() { bcs::to_bytes(&i).unwrap(), bcs::to_bytes(&j).unwrap(), ]; - tests.push(( - "0xcafe::test::str_vec_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec_vec", args, deserialization_failure())); // length over max size with 0 length strings let s_vec = vec![vec!["".as_bytes(); 3]; 100000]; @@ -603,11 +562,7 @@ fn string_args_bad_length() { bcs::to_bytes(&j).unwrap(), ]; - tests.push(( - "0xcafe::test::str_vec_vec", - args, - StatusCode::FAILED_TO_DESERIALIZE_ARGUMENT, - )); + tests.push(("0xcafe::test::str_vec_vec", args, deserialization_failure())); fail(tests); } diff --git a/aptos-move/e2e-move-tests/src/tests/token_objects.rs b/aptos-move/e2e-move-tests/src/tests/token_objects.rs index bdd7881ba089b..7899b52858797 100644 --- a/aptos-move/e2e-move-tests/src/tests/token_objects.rs +++ b/aptos-move/e2e-move-tests/src/tests/token_objects.rs @@ -69,7 +69,7 @@ fn test_basic_token() { type_params: vec![], }; let token_obj_tag = StructTag { - address: addr, + address: AccountAddress::from_hex_literal("0x4").unwrap(), module: Identifier::new("token").unwrap(), name: Identifier::new("Token").unwrap(), type_params: vec![], diff --git a/aptos-move/framework/aptos-token-objects/Move.toml b/aptos-move/framework/aptos-token-objects/Move.toml new file mode 100644 index 0000000000000..c60f18f8d8f40 --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/Move.toml @@ -0,0 +1,13 @@ +[package] +name = "AptosTokenObjects" +version = "1.0.0" + +[addresses] +std = "0x1" +aptos_std = "0x1" +aptos_framework = "0x1" +aptos_token_objects = "0x4" + +[dependencies] +MoveStdlib = { local = "../move-stdlib" } +AptosFramework = { local = "../aptos-framework"} diff --git a/aptos-move/framework/aptos-token-objects/doc/aptos_token.md b/aptos-move/framework/aptos-token-objects/doc/aptos_token.md new file mode 100644 index 0000000000000..f4eb9a1f870cd --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc/aptos_token.md @@ -0,0 +1,1397 @@ + +<a name="0x4_aptos_token"></a> + +# Module `0x4::aptos_token` + +This defines a minimally viable token for no-code solutions akin the the original token at +0x3::token module. +The key features are: +* Base token and collection features +* Creator definable mutability for tokens +* Creator-based freezing of tokens +* Standard object-based transfer and events +* Metadata property type + + +- [Resource `AptosCollection`](#0x4_aptos_token_AptosCollection) +- [Resource `AptosToken`](#0x4_aptos_token_AptosToken) +- [Constants](#@Constants_0) +- [Function `create_collection`](#0x4_aptos_token_create_collection) +- [Function `mint`](#0x4_aptos_token_mint) +- [Function `mint_soul_bound`](#0x4_aptos_token_mint_soul_bound) +- [Function `mint_internal`](#0x4_aptos_token_mint_internal) +- [Function `are_properties_mutable`](#0x4_aptos_token_are_properties_mutable) +- [Function `is_burnable`](#0x4_aptos_token_is_burnable) +- [Function `is_freezable_by_creator`](#0x4_aptos_token_is_freezable_by_creator) +- [Function `is_mutable_description`](#0x4_aptos_token_is_mutable_description) +- [Function `is_mutable_name`](#0x4_aptos_token_is_mutable_name) +- [Function `is_mutable_uri`](#0x4_aptos_token_is_mutable_uri) +- [Function `burn`](#0x4_aptos_token_burn) +- [Function `freeze_transfer`](#0x4_aptos_token_freeze_transfer) +- [Function `unfreeze_transfer`](#0x4_aptos_token_unfreeze_transfer) +- [Function `set_description`](#0x4_aptos_token_set_description) +- [Function `set_name`](#0x4_aptos_token_set_name) +- [Function `set_uri`](#0x4_aptos_token_set_uri) +- [Function `add_property`](#0x4_aptos_token_add_property) +- [Function `add_typed_property`](#0x4_aptos_token_add_typed_property) +- [Function `remove_property`](#0x4_aptos_token_remove_property) +- [Function `update_property`](#0x4_aptos_token_update_property) +- [Function `update_typed_property`](#0x4_aptos_token_update_typed_property) +- [Function `is_mutable_collection_description`](#0x4_aptos_token_is_mutable_collection_description) +- [Function `is_mutable_collection_royalty`](#0x4_aptos_token_is_mutable_collection_royalty) +- [Function `is_mutable_collection_uri`](#0x4_aptos_token_is_mutable_collection_uri) +- [Function `is_mutable_collection_token_description`](#0x4_aptos_token_is_mutable_collection_token_description) +- [Function `is_mutable_collection_token_name`](#0x4_aptos_token_is_mutable_collection_token_name) +- [Function `is_mutable_collection_token_uri`](#0x4_aptos_token_is_mutable_collection_token_uri) +- [Function `is_mutable_collection_token_properties`](#0x4_aptos_token_is_mutable_collection_token_properties) +- [Function `are_collection_tokens_burnable`](#0x4_aptos_token_are_collection_tokens_burnable) +- [Function `are_collection_tokens_freezable`](#0x4_aptos_token_are_collection_tokens_freezable) +- [Function `set_collection_description`](#0x4_aptos_token_set_collection_description) +- [Function `set_collection_royalties`](#0x4_aptos_token_set_collection_royalties) +- [Function `set_collection_royalties_call`](#0x4_aptos_token_set_collection_royalties_call) +- [Function `set_collection_uri`](#0x4_aptos_token_set_collection_uri) + + +<pre><code><b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error">0x1::error</a>; +<b>use</b> <a href="../../aptos-framework/doc/object.md#0x1_object">0x1::object</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option">0x1::option</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">0x1::signer</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string">0x1::string</a>; +<b>use</b> <a href="collection.md#0x4_collection">0x4::collection</a>; +<b>use</b> <a href="property_map.md#0x4_property_map">0x4::property_map</a>; +<b>use</b> <a href="royalty.md#0x4_royalty">0x4::royalty</a>; +<b>use</b> <a href="token.md#0x4_token">0x4::token</a>; +</code></pre> + + + +<a name="0x4_aptos_token_AptosCollection"></a> + +## Resource `AptosCollection` + +Storage state for managing the no-code Collection. + + +<pre><code><b>struct</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> <b>has</b> key +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>mutator_ref: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="collection.md#0x4_collection_MutatorRef">collection::MutatorRef</a>></code> +</dt> +<dd> + Used to mutate collection fields +</dd> +<dt> +<code>royalty_mutator_ref: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="royalty.md#0x4_royalty_MutatorRef">royalty::MutatorRef</a>></code> +</dt> +<dd> + Used to mutate royalties +</dd> +<dt> +<code>mutable_description: bool</code> +</dt> +<dd> + Determines if the creator can mutate the collection's description +</dd> +<dt> +<code>mutable_uri: bool</code> +</dt> +<dd> + Determines if the creator can mutate the collection's uri +</dd> +<dt> +<code>mutable_token_description: bool</code> +</dt> +<dd> + Determines if the creator can mutate token descriptions +</dd> +<dt> +<code>mutable_token_name: bool</code> +</dt> +<dd> + Determines if the creator can mutate token names +</dd> +<dt> +<code>mutable_token_properties: bool</code> +</dt> +<dd> + Determines if the creator can mutate token properties +</dd> +<dt> +<code>mutable_token_uri: bool</code> +</dt> +<dd> + Determines if the creator can mutate token uris +</dd> +<dt> +<code>tokens_burnable_by_creator: bool</code> +</dt> +<dd> + Determines if the creator can burn tokens +</dd> +<dt> +<code>tokens_freezable_by_creator: bool</code> +</dt> +<dd> + Determines if the creator can freeze tokens +</dd> +</dl> + + +</details> + +<a name="0x4_aptos_token_AptosToken"></a> + +## Resource `AptosToken` + +Storage state for managing the no-code Token. + + +<pre><code><b>struct</b> <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> <b>has</b> key +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>burn_ref: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="token.md#0x4_token_BurnRef">token::BurnRef</a>></code> +</dt> +<dd> + Used to burn. +</dd> +<dt> +<code>transfer_ref: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="../../aptos-framework/doc/object.md#0x1_object_TransferRef">object::TransferRef</a>></code> +</dt> +<dd> + Used to control freeze. +</dd> +<dt> +<code>mutator_ref: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="token.md#0x4_token_MutatorRef">token::MutatorRef</a>></code> +</dt> +<dd> + Used to mutate fields +</dd> +<dt> +<code>property_mutator_ref: <a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a></code> +</dt> +<dd> + Used to mutate properties +</dd> +</dl> + + +</details> + +<a name="@Constants_0"></a> + +## Constants + + +<a name="0x4_aptos_token_ECOLLECTION_DOES_NOT_EXIST"></a> + + + +<pre><code><b>const</b> <a href="aptos_token.md#0x4_aptos_token_ECOLLECTION_DOES_NOT_EXIST">ECOLLECTION_DOES_NOT_EXIST</a>: u64 = 1; +</code></pre> + + + +<a name="0x4_aptos_token_EFIELD_NOT_MUTABLE"></a> + +Attempted to mutate an immutable field + + +<pre><code><b>const</b> <a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>: u64 = 3; +</code></pre> + + + +<a name="0x4_aptos_token_ENOT_CREATOR"></a> + +The provided signer is not the creator + + +<pre><code><b>const</b> <a href="aptos_token.md#0x4_aptos_token_ENOT_CREATOR">ENOT_CREATOR</a>: u64 = 2; +</code></pre> + + + +<a name="0x4_aptos_token_ETOKEN_DOES_NOT_EXIST"></a> + + + +<pre><code><b>const</b> <a href="aptos_token.md#0x4_aptos_token_ETOKEN_DOES_NOT_EXIST">ETOKEN_DOES_NOT_EXIST</a>: u64 = 1; +</code></pre> + + + +<a name="0x4_aptos_token_EPROPERTIES_NOT_MUTABLE"></a> + +Attempted to mutate a property map that is not mutable + + +<pre><code><b>const</b> <a href="aptos_token.md#0x4_aptos_token_EPROPERTIES_NOT_MUTABLE">EPROPERTIES_NOT_MUTABLE</a>: u64 = 5; +</code></pre> + + + +<a name="0x4_aptos_token_ETOKEN_NOT_BURNABLE"></a> + +Attempted to burn a non-burnable token + + +<pre><code><b>const</b> <a href="aptos_token.md#0x4_aptos_token_ETOKEN_NOT_BURNABLE">ETOKEN_NOT_BURNABLE</a>: u64 = 4; +</code></pre> + + + +<a name="0x4_aptos_token_create_collection"></a> + +## Function `create_collection` + +Create a new collection + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_create_collection">create_collection</a>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, max_supply: u64, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, mutable_description: bool, mutable_royalty: bool, mutable_uri: bool, mutable_token_description: bool, mutable_token_name: bool, mutable_token_properties: bool, mutable_token_uri: bool, tokens_burnable_by_creator: bool, tokens_freezable_by_creator: bool, royalty_numerator: u64, royalty_denominator: u64) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_create_collection">create_collection</a>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + description: String, + max_supply: u64, + name: String, + uri: String, + mutable_description: bool, + mutable_royalty: bool, + mutable_uri: bool, + mutable_token_description: bool, + mutable_token_name: bool, + mutable_token_properties: bool, + mutable_token_uri: bool, + tokens_burnable_by_creator: bool, + tokens_freezable_by_creator: bool, + royalty_numerator: u64, + royalty_denominator: u64, +) { + <b>let</b> creator_addr = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator); + <b>let</b> <a href="royalty.md#0x4_royalty">royalty</a> = <a href="royalty.md#0x4_royalty_create">royalty::create</a>(royalty_numerator, royalty_denominator, creator_addr); + <b>let</b> constructor_ref = <a href="collection.md#0x4_collection_create_fixed_collection">collection::create_fixed_collection</a>( + creator, + description, + max_supply, + name, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(<a href="royalty.md#0x4_royalty">royalty</a>), + uri, + ); + + <b>let</b> object_signer = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_signer">object::generate_signer</a>(&constructor_ref); + <b>let</b> mutator_ref = <b>if</b> (mutable_description || mutable_uri) { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(<a href="collection.md#0x4_collection_generate_mutator_ref">collection::generate_mutator_ref</a>(&constructor_ref)) + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>() + }; + + <b>let</b> royalty_mutator_ref = <b>if</b> (mutable_royalty) { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(<a href="royalty.md#0x4_royalty_generate_mutator_ref">royalty::generate_mutator_ref</a>(<a href="../../aptos-framework/doc/object.md#0x1_object_generate_extend_ref">object::generate_extend_ref</a>(&constructor_ref))) + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>() + }; + + <b>let</b> aptos_collection = <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + mutator_ref, + royalty_mutator_ref, + mutable_description, + mutable_uri, + mutable_token_description, + mutable_token_name, + mutable_token_properties, + mutable_token_uri, + tokens_burnable_by_creator, + tokens_freezable_by_creator, + }; + <b>move_to</b>(&object_signer, aptos_collection); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_mint"></a> + +## Function `mint` + +With an existing collection, directly mint a viable token into the creators account. + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_mint">mint</a>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, property_keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, property_types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, property_values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_mint">mint</a>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="collection.md#0x4_collection">collection</a>: String, + description: String, + name: String, + uri: String, + property_keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + property_types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + property_values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> constructor_ref = <a href="aptos_token.md#0x4_aptos_token_mint_internal">mint_internal</a>( + creator, + <a href="collection.md#0x4_collection">collection</a>, + description, + name, + uri, + property_keys, + property_types, + property_values, + ); + + <b>let</b> <a href="collection.md#0x4_collection">collection</a> = collection_object(creator, &<a href="collection.md#0x4_collection">collection</a>); + <b>let</b> freezable_by_creator = <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_freezable">are_collection_tokens_freezable</a>(<a href="collection.md#0x4_collection">collection</a>); + <b>if</b> (!freezable_by_creator) { + <b>return</b> + }; + + <b>let</b> aptos_token_addr = <a href="../../aptos-framework/doc/object.md#0x1_object_address_from_constructor_ref">object::address_from_constructor_ref</a>(&constructor_ref); + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = <b>borrow_global_mut</b><<a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a>>(aptos_token_addr); + <b>let</b> transfer_ref = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_transfer_ref">object::generate_transfer_ref</a>(&constructor_ref); + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_fill">option::fill</a>(&<b>mut</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.transfer_ref, transfer_ref); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_mint_soul_bound"></a> + +## Function `mint_soul_bound` + +With an existing collection, directly mint a soul bound token into the recipient's account. + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_mint_soul_bound">mint_soul_bound</a>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, property_keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, property_types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, property_values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>, soul_bound_to: <b>address</b>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_mint_soul_bound">mint_soul_bound</a>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="collection.md#0x4_collection">collection</a>: String, + description: String, + name: String, + uri: String, + property_keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + property_types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + property_values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>, + soul_bound_to: <b>address</b>, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <b>let</b> constructor_ref = <a href="aptos_token.md#0x4_aptos_token_mint_internal">mint_internal</a>( + creator, + <a href="collection.md#0x4_collection">collection</a>, + description, + name, + uri, + property_keys, + property_types, + property_values, + ); + + <b>let</b> transfer_ref = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_transfer_ref">object::generate_transfer_ref</a>(&constructor_ref); + <b>let</b> linear_transfer_ref = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_linear_transfer_ref">object::generate_linear_transfer_ref</a>(&transfer_ref); + <a href="../../aptos-framework/doc/object.md#0x1_object_transfer_with_ref">object::transfer_with_ref</a>(linear_transfer_ref, soul_bound_to); + <a href="../../aptos-framework/doc/object.md#0x1_object_disable_ungated_transfer">object::disable_ungated_transfer</a>(&transfer_ref); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_mint_internal"></a> + +## Function `mint_internal` + + + +<pre><code><b>fun</b> <a href="aptos_token.md#0x4_aptos_token_mint_internal">mint_internal</a>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, property_keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, property_types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, property_values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>): <a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>fun</b> <a href="aptos_token.md#0x4_aptos_token_mint_internal">mint_internal</a>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="collection.md#0x4_collection">collection</a>: String, + description: String, + name: String, + uri: String, + property_keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + property_types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + property_values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>, +): ConstructorRef <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <b>let</b> constructor_ref = <a href="token.md#0x4_token_create">token::create</a>( + creator, + <a href="collection.md#0x4_collection">collection</a>, + description, + name, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>(), + uri, + ); + + <b>let</b> object_signer = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_signer">object::generate_signer</a>(&constructor_ref); + + <b>let</b> collection_obj = collection_object(creator, &<a href="collection.md#0x4_collection">collection</a>); + <b>let</b> <a href="collection.md#0x4_collection">collection</a> = borrow_collection(&collection_obj); + + <b>let</b> mutator_ref = <b>if</b> ( + <a href="collection.md#0x4_collection">collection</a>.mutable_token_description + || <a href="collection.md#0x4_collection">collection</a>.mutable_token_name + || <a href="collection.md#0x4_collection">collection</a>.mutable_token_uri + ) { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(<a href="token.md#0x4_token_generate_mutator_ref">token::generate_mutator_ref</a>(&constructor_ref)) + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>() + }; + + <b>let</b> burn_ref = <b>if</b> (<a href="collection.md#0x4_collection">collection</a>.tokens_burnable_by_creator) { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(<a href="token.md#0x4_token_generate_burn_ref">token::generate_burn_ref</a>(&constructor_ref)) + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>() + }; + + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + burn_ref, + transfer_ref: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>(), + mutator_ref, + property_mutator_ref: <a href="property_map.md#0x4_property_map_generate_mutator_ref">property_map::generate_mutator_ref</a>(&constructor_ref), + }; + <b>move_to</b>(&object_signer, <a href="aptos_token.md#0x4_aptos_token">aptos_token</a>); + + <b>let</b> properties = <a href="property_map.md#0x4_property_map_prepare_input">property_map::prepare_input</a>(property_keys, property_types, property_values); + <a href="property_map.md#0x4_property_map_init">property_map::init</a>(&constructor_ref, properties); + + constructor_ref +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_are_properties_mutable"></a> + +## Function `are_properties_mutable` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_are_properties_mutable">are_properties_mutable</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_are_properties_mutable">are_properties_mutable</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <b>let</b> <a href="collection.md#0x4_collection">collection</a> = <a href="token.md#0x4_token_collection_object">token::collection_object</a>(<a href="token.md#0x4_token">token</a>); + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).mutable_token_properties +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_burnable"></a> + +## Function `is_burnable` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_burnable">is_burnable</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_burnable">is_burnable</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&borrow(&<a href="token.md#0x4_token">token</a>).burn_ref) +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_freezable_by_creator"></a> + +## Function `is_freezable_by_creator` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_freezable_by_creator">is_freezable_by_creator</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_freezable_by_creator">is_freezable_by_creator</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_freezable">are_collection_tokens_freezable</a>(<a href="token.md#0x4_token_collection_object">token::collection_object</a>(<a href="token.md#0x4_token">token</a>)) +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_description"></a> + +## Function `is_mutable_description` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_description">is_mutable_description</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_description">is_mutable_description</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_description">is_mutable_collection_token_description</a>(<a href="token.md#0x4_token_collection_object">token::collection_object</a>(<a href="token.md#0x4_token">token</a>)) +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_name"></a> + +## Function `is_mutable_name` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_name">is_mutable_name</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_name">is_mutable_name</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_name">is_mutable_collection_token_name</a>(<a href="token.md#0x4_token_collection_object">token::collection_object</a>(<a href="token.md#0x4_token">token</a>)) +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_uri"></a> + +## Function `is_mutable_uri` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_uri">is_mutable_uri</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_uri">is_mutable_uri</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_uri">is_mutable_collection_token_uri</a>(<a href="token.md#0x4_token_collection_object">token::collection_object</a>(<a href="token.md#0x4_token">token</a>)) +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_burn"></a> + +## Function `burn` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_burn">burn</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_burn">burn</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: Object<T>) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.burn_ref), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_ETOKEN_NOT_BURNABLE">ETOKEN_NOT_BURNABLE</a>), + ); + <b>move</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a>; + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = <b>move_from</b><<a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a>>(<a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(&<a href="token.md#0x4_token">token</a>)); + <b>let</b> <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + burn_ref, + transfer_ref: _, + mutator_ref: _, + property_mutator_ref, + } = <a href="aptos_token.md#0x4_aptos_token">aptos_token</a>; + <a href="property_map.md#0x4_property_map_burn">property_map::burn</a>(property_mutator_ref); + <a href="token.md#0x4_token_burn">token::burn</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_extract">option::extract</a>(&<b>mut</b> burn_ref)); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_freeze_transfer"></a> + +## Function `freeze_transfer` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_freeze_transfer">freeze_transfer</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_freeze_transfer">freeze_transfer</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: Object<T>) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_freezable">are_collection_tokens_freezable</a>(<a href="token.md#0x4_token_collection_object">token::collection_object</a>(<a href="token.md#0x4_token">token</a>)) + && <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.transfer_ref), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <a href="../../aptos-framework/doc/object.md#0x1_object_disable_ungated_transfer">object::disable_ungated_transfer</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.transfer_ref)); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_unfreeze_transfer"></a> + +## Function `unfreeze_transfer` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_unfreeze_transfer">unfreeze_transfer</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_unfreeze_transfer">unfreeze_transfer</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: Object<T>) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_freezable">are_collection_tokens_freezable</a>(<a href="token.md#0x4_token_collection_object">token::collection_object</a>(<a href="token.md#0x4_token">token</a>)) + && <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.transfer_ref), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <a href="../../aptos-framework/doc/object.md#0x1_object_enable_ungated_transfer">object::enable_ungated_transfer</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.transfer_ref)); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_set_description"></a> + +## Function `set_description` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_description">set_description</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_description">set_description</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + description: String, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_is_mutable_description">is_mutable_description</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <a href="token.md#0x4_token_set_description">token::set_description</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.mutator_ref), description); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_set_name"></a> + +## Function `set_name` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_name">set_name</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_name">set_name</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + name: String, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_is_mutable_name">is_mutable_name</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <a href="token.md#0x4_token_set_name">token::set_name</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.mutator_ref), name); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_set_uri"></a> + +## Function `set_uri` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_uri">set_uri</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_uri">set_uri</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + uri: String, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_is_mutable_uri">is_mutable_uri</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <a href="token.md#0x4_token_set_uri">token::set_uri</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.mutator_ref), uri); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_add_property"></a> + +## Function `add_property` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_add_property">add_property</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, type: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_add_property">add_property</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + key: String, + type: String, + value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_are_properties_mutable">are_properties_mutable</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EPROPERTIES_NOT_MUTABLE">EPROPERTIES_NOT_MUTABLE</a>), + ); + + <a href="property_map.md#0x4_property_map_add">property_map::add</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.property_mutator_ref, key, type, value); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_add_typed_property"></a> + +## Function `add_typed_property` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_add_typed_property">add_typed_property</a><T: key, V: drop>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: V) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_add_typed_property">add_typed_property</a><T: key, V: drop>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + key: String, + value: V, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_are_properties_mutable">are_properties_mutable</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EPROPERTIES_NOT_MUTABLE">EPROPERTIES_NOT_MUTABLE</a>), + ); + + <a href="property_map.md#0x4_property_map_add_typed">property_map::add_typed</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.property_mutator_ref, key, value); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_remove_property"></a> + +## Function `remove_property` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_remove_property">remove_property</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_remove_property">remove_property</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + key: String, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_are_properties_mutable">are_properties_mutable</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EPROPERTIES_NOT_MUTABLE">EPROPERTIES_NOT_MUTABLE</a>), + ); + + <a href="property_map.md#0x4_property_map_remove">property_map::remove</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.property_mutator_ref, &key); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_update_property"></a> + +## Function `update_property` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_update_property">update_property</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, type: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_update_property">update_property</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + key: String, + type: String, + value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_are_properties_mutable">are_properties_mutable</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EPROPERTIES_NOT_MUTABLE">EPROPERTIES_NOT_MUTABLE</a>), + ); + + <a href="property_map.md#0x4_property_map_update">property_map::update</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.property_mutator_ref, &key, type, value); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_update_typed_property"></a> + +## Function `update_typed_property` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_update_typed_property">update_typed_property</a><T: key, V: drop>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: V) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_update_typed_property">update_typed_property</a><T: key, V: drop>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="token.md#0x4_token">token</a>: Object<T>, + key: String, + value: V, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a>, <a href="aptos_token.md#0x4_aptos_token_AptosToken">AptosToken</a> { + <b>let</b> <a href="aptos_token.md#0x4_aptos_token">aptos_token</a> = authorized_borrow(&<a href="token.md#0x4_token">token</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="aptos_token.md#0x4_aptos_token_are_properties_mutable">are_properties_mutable</a>(<a href="token.md#0x4_token">token</a>), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EPROPERTIES_NOT_MUTABLE">EPROPERTIES_NOT_MUTABLE</a>), + ); + + <a href="property_map.md#0x4_property_map_update_typed">property_map::update_typed</a>(&<a href="aptos_token.md#0x4_aptos_token">aptos_token</a>.property_mutator_ref, &key, value); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_collection_description"></a> + +## Function `is_mutable_collection_description` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_description">is_mutable_collection_description</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_description">is_mutable_collection_description</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).mutable_description +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_collection_royalty"></a> + +## Function `is_mutable_collection_royalty` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_royalty">is_mutable_collection_royalty</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_royalty">is_mutable_collection_royalty</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).royalty_mutator_ref) +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_collection_uri"></a> + +## Function `is_mutable_collection_uri` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_uri">is_mutable_collection_uri</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_uri">is_mutable_collection_uri</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).mutable_uri +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_collection_token_description"></a> + +## Function `is_mutable_collection_token_description` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_description">is_mutable_collection_token_description</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_description">is_mutable_collection_token_description</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).mutable_token_description +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_collection_token_name"></a> + +## Function `is_mutable_collection_token_name` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_name">is_mutable_collection_token_name</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_name">is_mutable_collection_token_name</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).mutable_token_name +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_collection_token_uri"></a> + +## Function `is_mutable_collection_token_uri` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_uri">is_mutable_collection_token_uri</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_uri">is_mutable_collection_token_uri</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).mutable_token_uri +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_is_mutable_collection_token_properties"></a> + +## Function `is_mutable_collection_token_properties` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_properties">is_mutable_collection_token_properties</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_is_mutable_collection_token_properties">is_mutable_collection_token_properties</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).mutable_token_properties +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_are_collection_tokens_burnable"></a> + +## Function `are_collection_tokens_burnable` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_burnable">are_collection_tokens_burnable</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_burnable">are_collection_tokens_burnable</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).tokens_burnable_by_creator +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_are_collection_tokens_freezable"></a> + +## Function `are_collection_tokens_freezable` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_freezable">are_collection_tokens_freezable</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_are_collection_tokens_freezable">are_collection_tokens_freezable</a><T: key>( + <a href="collection.md#0x4_collection">collection</a>: Object<T>, +): bool <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + borrow_collection(&<a href="collection.md#0x4_collection">collection</a>).tokens_freezable_by_creator +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_set_collection_description"></a> + +## Function `set_collection_description` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_description">set_collection_description</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_description">set_collection_description</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="collection.md#0x4_collection">collection</a>: Object<T>, + description: String, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <b>let</b> aptos_collection = authorized_borrow_collection(&<a href="collection.md#0x4_collection">collection</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + aptos_collection.mutable_description, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <a href="collection.md#0x4_collection_set_description">collection::set_description</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&aptos_collection.mutator_ref), description); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_set_collection_royalties"></a> + +## Function `set_collection_royalties` + + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_royalties">set_collection_royalties</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_royalties">set_collection_royalties</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="collection.md#0x4_collection">collection</a>: Object<T>, + <a href="royalty.md#0x4_royalty">royalty</a>: <a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <b>let</b> aptos_collection = authorized_borrow_collection(&<a href="collection.md#0x4_collection">collection</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&aptos_collection.royalty_mutator_ref), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <a href="royalty.md#0x4_royalty_update">royalty::update</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&aptos_collection.royalty_mutator_ref), <a href="royalty.md#0x4_royalty">royalty</a>); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_set_collection_royalties_call"></a> + +## Function `set_collection_royalties_call` + + + +<pre><code>entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_royalties_call">set_collection_royalties_call</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, royalty_numerator: u64, royalty_denominator: u64, payee_address: <b>address</b>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code>entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_royalties_call">set_collection_royalties_call</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="collection.md#0x4_collection">collection</a>: Object<T>, + royalty_numerator: u64, + royalty_denominator: u64, + payee_address: <b>address</b>, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <b>let</b> <a href="royalty.md#0x4_royalty">royalty</a> = <a href="royalty.md#0x4_royalty_create">royalty::create</a>(royalty_numerator, royalty_denominator, payee_address); + <a href="aptos_token.md#0x4_aptos_token_set_collection_royalties">set_collection_royalties</a>(creator, <a href="collection.md#0x4_collection">collection</a>, <a href="royalty.md#0x4_royalty">royalty</a>); +} +</code></pre> + + + +</details> + +<a name="0x4_aptos_token_set_collection_uri"></a> + +## Function `set_collection_uri` + + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_uri">set_collection_uri</a><T: key>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> entry <b>fun</b> <a href="aptos_token.md#0x4_aptos_token_set_collection_uri">set_collection_uri</a><T: key>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + <a href="collection.md#0x4_collection">collection</a>: Object<T>, + uri: String, +) <b>acquires</b> <a href="aptos_token.md#0x4_aptos_token_AptosCollection">AptosCollection</a> { + <b>let</b> aptos_collection = authorized_borrow_collection(&<a href="collection.md#0x4_collection">collection</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator)); + <b>assert</b>!( + aptos_collection.mutable_uri, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_permission_denied">error::permission_denied</a>(<a href="aptos_token.md#0x4_aptos_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>), + ); + <a href="collection.md#0x4_collection_set_uri">collection::set_uri</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&aptos_collection.mutator_ref), uri); +} +</code></pre> + + + +</details> + + +[move-book]: https://move-language.github.io/move/introduction.html diff --git a/aptos-move/framework/aptos-token-objects/doc/collection.md b/aptos-move/framework/aptos-token-objects/doc/collection.md new file mode 100644 index 0000000000000..dbe52641b6cd7 --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc/collection.md @@ -0,0 +1,658 @@ + +<a name="0x4_collection"></a> + +# Module `0x4::collection` + +This defines an object-based Collection. A collection acts as a set organizer for a group of +tokens. This includes aspects such as a general description, project URI, name, and may contain +other useful generalizations across this set of tokens. + +Being built upon objects enables collections to be relatively flexible. As core primitives it +supports: +* Common fields: name, uri, description, creator +* MutatorRef leaving mutability configuration to a higher level component +* Addressed by a global identifier of creator's address and collection name, thus collections +cannot be deleted as a restriction of the object model. +* Optional support for collection-wide royalties +* Optional support for tracking of supply + +This collection does not directly support: +* Events on mint or burn -- that's left to the collection creator. + +TODO: +* Consider supporting changing the name of the collection with the MutatorRef. This would +require adding the field original_name. +* Consider supporting changing the aspects of supply with the MutatorRef. +* Add aggregator support when added to framework +* Update Object<T> to be viable input as a transaction arg and then update all readers as view. + + +- [Resource `Collection`](#0x4_collection_Collection) +- [Struct `MutatorRef`](#0x4_collection_MutatorRef) +- [Struct `MutationEvent`](#0x4_collection_MutationEvent) +- [Resource `FixedSupply`](#0x4_collection_FixedSupply) +- [Constants](#@Constants_0) +- [Function `create_fixed_collection`](#0x4_collection_create_fixed_collection) +- [Function `create_untracked_collection`](#0x4_collection_create_untracked_collection) +- [Function `create_collection_address`](#0x4_collection_create_collection_address) +- [Function `create_collection_seed`](#0x4_collection_create_collection_seed) +- [Function `increment_supply`](#0x4_collection_increment_supply) +- [Function `decrement_supply`](#0x4_collection_decrement_supply) +- [Function `generate_mutator_ref`](#0x4_collection_generate_mutator_ref) +- [Function `count`](#0x4_collection_count) +- [Function `creator`](#0x4_collection_creator) +- [Function `description`](#0x4_collection_description) +- [Function `name`](#0x4_collection_name) +- [Function `uri`](#0x4_collection_uri) +- [Function `set_description`](#0x4_collection_set_description) +- [Function `set_uri`](#0x4_collection_set_uri) + + +<pre><code><b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error">0x1::error</a>; +<b>use</b> <a href="../../aptos-framework/doc/event.md#0x1_event">0x1::event</a>; +<b>use</b> <a href="../../aptos-framework/doc/object.md#0x1_object">0x1::object</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option">0x1::option</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">0x1::signer</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string">0x1::string</a>; +<b>use</b> <a href="royalty.md#0x4_royalty">0x4::royalty</a>; +</code></pre> + + + +<a name="0x4_collection_Collection"></a> + +## Resource `Collection` + +Represents the common fields for a collection. + + +<pre><code><b>struct</b> <a href="collection.md#0x4_collection_Collection">Collection</a> <b>has</b> key +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>creator: <b>address</b></code> +</dt> +<dd> + The creator of this collection. +</dd> +<dt> +<code>description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + A brief description of the collection. +</dd> +<dt> +<code>name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + An optional categorization of similar token. +</dd> +<dt> +<code>uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + 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? +</dd> +<dt> +<code>mutation_events: <a href="../../aptos-framework/doc/event.md#0x1_event_EventHandle">event::EventHandle</a><<a href="collection.md#0x4_collection_MutationEvent">collection::MutationEvent</a>></code> +</dt> +<dd> + Emitted upon any mutation of the collection. +</dd> +</dl> + + +</details> + +<a name="0x4_collection_MutatorRef"></a> + +## Struct `MutatorRef` + +This enables mutating description and URI by higher level services. + + +<pre><code><b>struct</b> <a href="collection.md#0x4_collection_MutatorRef">MutatorRef</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>self: <b>address</b></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="0x4_collection_MutationEvent"></a> + +## 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. + + +<pre><code><b>struct</b> <a href="collection.md#0x4_collection_MutationEvent">MutationEvent</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>mutated_field_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="0x4_collection_FixedSupply"></a> + +## Resource `FixedSupply` + +Fixed supply tracker, this is useful for ensuring that a limited number of tokens are minted. + + +<pre><code><b>struct</b> <a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a> <b>has</b> key +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>current_supply: u64</code> +</dt> +<dd> + +</dd> +<dt> +<code>max_supply: u64</code> +</dt> +<dd> + +</dd> +<dt> +<code>total_minted: u64</code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="@Constants_0"></a> + +## Constants + + +<a name="0x4_collection_ECOLLECTION_DOES_NOT_EXIST"></a> + +The collection does not exist + + +<pre><code><b>const</b> <a href="collection.md#0x4_collection_ECOLLECTION_DOES_NOT_EXIST">ECOLLECTION_DOES_NOT_EXIST</a>: u64 = 2; +</code></pre> + + + +<a name="0x4_collection_EEXCEEDS_MAX_SUPPLY"></a> + +The collections supply is at its maximum amount + + +<pre><code><b>const</b> <a href="collection.md#0x4_collection_EEXCEEDS_MAX_SUPPLY">EEXCEEDS_MAX_SUPPLY</a>: u64 = 1; +</code></pre> + + + +<a name="0x4_collection_create_fixed_collection"></a> + +## Function `create_fixed_collection` + +Creates a fixed-sized collection, or a collection that supports a fixed amount of tokens. +This is useful to create a guaranteed, limited supply on-chain digital asset. For example, +a collection 1111 vicious vipers. Note, creating restrictions such as upward limits results +in data structures that prevent Aptos from parallelizing mints of this collection type. + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_fixed_collection">create_fixed_collection</a>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, max_supply: u64, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_fixed_collection">create_fixed_collection</a>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + description: String, + max_supply: u64, + name: String, + <a href="royalty.md#0x4_royalty">royalty</a>: Option<Royalty>, + uri: String, +): ConstructorRef { + <b>let</b> supply = <a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a> { + current_supply: 0, + max_supply, + total_minted: 0, + }; + + create_collection_internal( + creator, + description, + name, + <a href="royalty.md#0x4_royalty">royalty</a>, + uri, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(supply), + ) +} +</code></pre> + + + +</details> + +<a name="0x4_collection_create_untracked_collection"></a> + +## Function `create_untracked_collection` + +Creates an untracked collection, or a collection that supports an arbitrary amount of +tokens. This is useful for mass airdrops that fully leverage Aptos parallelization. + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_untracked_collection">create_untracked_collection</a>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_untracked_collection">create_untracked_collection</a>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + description: String, + name: String, + <a href="royalty.md#0x4_royalty">royalty</a>: Option<Royalty>, + uri: String, +): ConstructorRef { + create_collection_internal<<a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a>>( + creator, + description, + name, + <a href="royalty.md#0x4_royalty">royalty</a>, + uri, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>(), + ) +} +</code></pre> + + + +</details> + +<a name="0x4_collection_create_collection_address"></a> + +## Function `create_collection_address` + +Generates the collections address based upon the creators address and the collection's name + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_collection_address">create_collection_address</a>(creator: &<b>address</b>, name: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <b>address</b> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_collection_address">create_collection_address</a>(creator: &<b>address</b>, name: &String): <b>address</b> { + <a href="../../aptos-framework/doc/object.md#0x1_object_create_object_address">object::create_object_address</a>(creator, <a href="collection.md#0x4_collection_create_collection_seed">create_collection_seed</a>(name)) +} +</code></pre> + + + +</details> + +<a name="0x4_collection_create_collection_seed"></a> + +## Function `create_collection_seed` + +Named objects are derived from a seed, the collection's seed is its name. + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_collection_seed">create_collection_seed</a>(name: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_create_collection_seed">create_collection_seed</a>(name: &String): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8> { + *<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_bytes">string::bytes</a>(name) +} +</code></pre> + + + +</details> + +<a name="0x4_collection_increment_supply"></a> + +## Function `increment_supply` + +Called by token on mint to increment supply if there's an appropriate Supply struct. + + +<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="collection.md#0x4_collection_increment_supply">increment_supply</a>(<a href="collection.md#0x4_collection">collection</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><<a href="collection.md#0x4_collection_Collection">collection::Collection</a>>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><u64> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="collection.md#0x4_collection_increment_supply">increment_supply</a>( + <a href="collection.md#0x4_collection">collection</a>: &Object<<a href="collection.md#0x4_collection_Collection">Collection</a>>, +): Option<u64> <b>acquires</b> <a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a> { + <b>let</b> collection_addr = <a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="collection.md#0x4_collection">collection</a>); + <b>if</b> (<b>exists</b><<a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a>>(collection_addr)) { + <b>let</b> supply = <b>borrow_global_mut</b><<a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a>>(collection_addr); + supply.current_supply = supply.current_supply + 1; + supply.total_minted = supply.total_minted + 1; + <b>assert</b>!( + supply.current_supply <= supply.max_supply, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_out_of_range">error::out_of_range</a>(<a href="collection.md#0x4_collection_EEXCEEDS_MAX_SUPPLY">EEXCEEDS_MAX_SUPPLY</a>), + ); + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(supply.total_minted) + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>() + } +} +</code></pre> + + + +</details> + +<a name="0x4_collection_decrement_supply"></a> + +## Function `decrement_supply` + +Called by token on burn to decrement supply if there's an appropriate Supply struct. + + +<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="collection.md#0x4_collection_decrement_supply">decrement_supply</a>(<a href="collection.md#0x4_collection">collection</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><<a href="collection.md#0x4_collection_Collection">collection::Collection</a>>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="collection.md#0x4_collection_decrement_supply">decrement_supply</a>(<a href="collection.md#0x4_collection">collection</a>: &Object<<a href="collection.md#0x4_collection_Collection">Collection</a>>) <b>acquires</b> <a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a> { + <b>let</b> collection_addr = <a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="collection.md#0x4_collection">collection</a>); + <b>if</b> (<b>exists</b><<a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a>>(collection_addr)) { + <b>let</b> supply = <b>borrow_global_mut</b><<a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a>>(collection_addr); + supply.current_supply = supply.current_supply - 1; + } +} +</code></pre> + + + +</details> + +<a name="0x4_collection_generate_mutator_ref"></a> + +## Function `generate_mutator_ref` + +Creates a MutatorRef, which gates the ability to mutate any fields that support mutation. + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_generate_mutator_ref">generate_mutator_ref</a>(ref: &<a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a>): <a href="collection.md#0x4_collection_MutatorRef">collection::MutatorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_generate_mutator_ref">generate_mutator_ref</a>(ref: &ConstructorRef): <a href="collection.md#0x4_collection_MutatorRef">MutatorRef</a> { + <b>let</b> <a href="../../aptos-framework/doc/object.md#0x1_object">object</a> = <a href="../../aptos-framework/doc/object.md#0x1_object_object_from_constructor_ref">object::object_from_constructor_ref</a><<a href="collection.md#0x4_collection_Collection">Collection</a>>(ref); + <a href="collection.md#0x4_collection_MutatorRef">MutatorRef</a> { self: <a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(&<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>) } +} +</code></pre> + + + +</details> + +<a name="0x4_collection_count"></a> + +## Function `count` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_count">count</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><u64> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_count">count</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: Object<T>): Option<u64> <b>acquires</b> <a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a> { + <b>let</b> collection_address = <a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(&<a href="collection.md#0x4_collection">collection</a>); + <b>assert</b>!( + <b>exists</b><<a href="collection.md#0x4_collection_Collection">Collection</a>>(collection_address), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="collection.md#0x4_collection_ECOLLECTION_DOES_NOT_EXIST">ECOLLECTION_DOES_NOT_EXIST</a>), + ); + + <b>if</b> (<b>exists</b><<a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a>>(collection_address)) { + <b>let</b> supply = <b>borrow_global_mut</b><<a href="collection.md#0x4_collection_FixedSupply">FixedSupply</a>>(collection_address); + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(supply.current_supply) + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>() + } +} +</code></pre> + + + +</details> + +<a name="0x4_collection_creator"></a> + +## Function `creator` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_creator">creator</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <b>address</b> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_creator">creator</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: Object<T>): <b>address</b> <b>acquires</b> <a href="collection.md#0x4_collection_Collection">Collection</a> { + borrow(&<a href="collection.md#0x4_collection">collection</a>).creator +} +</code></pre> + + + +</details> + +<a name="0x4_collection_description"></a> + +## Function `description` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_description">description</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_description">description</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: Object<T>): String <b>acquires</b> <a href="collection.md#0x4_collection_Collection">Collection</a> { + borrow(&<a href="collection.md#0x4_collection">collection</a>).description +} +</code></pre> + + + +</details> + +<a name="0x4_collection_name"></a> + +## Function `name` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_name">name</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_name">name</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: Object<T>): String <b>acquires</b> <a href="collection.md#0x4_collection_Collection">Collection</a> { + borrow(&<a href="collection.md#0x4_collection">collection</a>).name +} +</code></pre> + + + +</details> + +<a name="0x4_collection_uri"></a> + +## Function `uri` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_uri">uri</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_uri">uri</a><T: key>(<a href="collection.md#0x4_collection">collection</a>: Object<T>): String <b>acquires</b> <a href="collection.md#0x4_collection_Collection">Collection</a> { + borrow(&<a href="collection.md#0x4_collection">collection</a>).uri +} +</code></pre> + + + +</details> + +<a name="0x4_collection_set_description"></a> + +## Function `set_description` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_set_description">set_description</a>(mutator_ref: &<a href="collection.md#0x4_collection_MutatorRef">collection::MutatorRef</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_set_description">set_description</a>(mutator_ref: &<a href="collection.md#0x4_collection_MutatorRef">MutatorRef</a>, description: String) <b>acquires</b> <a href="collection.md#0x4_collection_Collection">Collection</a> { + <b>let</b> <a href="collection.md#0x4_collection">collection</a> = borrow_mut(mutator_ref); + <a href="collection.md#0x4_collection">collection</a>.description = description; + <a href="../../aptos-framework/doc/event.md#0x1_event_emit_event">event::emit_event</a>( + &<b>mut</b> <a href="collection.md#0x4_collection">collection</a>.mutation_events, + <a href="collection.md#0x4_collection_MutationEvent">MutationEvent</a> { mutated_field_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_utf8">string::utf8</a>(b"description") }, + ); +} +</code></pre> + + + +</details> + +<a name="0x4_collection_set_uri"></a> + +## Function `set_uri` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_set_uri">set_uri</a>(mutator_ref: &<a href="collection.md#0x4_collection_MutatorRef">collection::MutatorRef</a>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection_set_uri">set_uri</a>(mutator_ref: &<a href="collection.md#0x4_collection_MutatorRef">MutatorRef</a>, uri: String) <b>acquires</b> <a href="collection.md#0x4_collection_Collection">Collection</a> { + <b>let</b> <a href="collection.md#0x4_collection">collection</a> = borrow_mut(mutator_ref); + <a href="collection.md#0x4_collection">collection</a>.uri = uri; + <a href="../../aptos-framework/doc/event.md#0x1_event_emit_event">event::emit_event</a>( + &<b>mut</b> <a href="collection.md#0x4_collection">collection</a>.mutation_events, + <a href="collection.md#0x4_collection_MutationEvent">MutationEvent</a> { mutated_field_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_utf8">string::utf8</a>(b"uri") }, + ); +} +</code></pre> + + + +</details> + + +[move-book]: https://move-language.github.io/move/introduction.html diff --git a/aptos-move/framework/aptos-token-objects/doc/overview.md b/aptos-move/framework/aptos-token-objects/doc/overview.md new file mode 100644 index 0000000000000..95871073813d9 --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc/overview.md @@ -0,0 +1,22 @@ + +<a name="@Aptos_Token_Framework_0"></a> + +# Aptos Token Framework + + +This is the reference documentation of the Aptos Token Objects framework. + + +<a name="@Index_1"></a> + +## Index + + +- [`0x4::aptos_token`](aptos_token.md#0x4_aptos_token) +- [`0x4::collection`](collection.md#0x4_collection) +- [`0x4::property_map`](property_map.md#0x4_property_map) +- [`0x4::royalty`](royalty.md#0x4_royalty) +- [`0x4::token`](token.md#0x4_token) + + +[move-book]: https://move-language.github.io/move/introduction.html diff --git a/aptos-move/framework/aptos-token-objects/doc/property_map.md b/aptos-move/framework/aptos-token-objects/doc/property_map.md new file mode 100644 index 0000000000000..8ab1b5390cb44 --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc/property_map.md @@ -0,0 +1,978 @@ + +<a name="0x4_property_map"></a> + +# Module `0x4::property_map` + +PropertyMap provides generic metadata support for AptosToken. It is a specialization of +SimpleMap that enforces strict typing with minimal storage use by using constant u64 to +represent types and storing values in bcs format. + + +- [Resource `PropertyMap`](#0x4_property_map_PropertyMap) +- [Struct `PropertyValue`](#0x4_property_map_PropertyValue) +- [Struct `MutatorRef`](#0x4_property_map_MutatorRef) +- [Constants](#@Constants_0) +- [Function `init`](#0x4_property_map_init) +- [Function `burn`](#0x4_property_map_burn) +- [Function `prepare_input`](#0x4_property_map_prepare_input) +- [Function `generate_mutator_ref`](#0x4_property_map_generate_mutator_ref) +- [Function `contains_key`](#0x4_property_map_contains_key) +- [Function `length`](#0x4_property_map_length) +- [Function `read`](#0x4_property_map_read) +- [Function `read_bool`](#0x4_property_map_read_bool) +- [Function `read_u8`](#0x4_property_map_read_u8) +- [Function `read_u16`](#0x4_property_map_read_u16) +- [Function `read_u32`](#0x4_property_map_read_u32) +- [Function `read_u64`](#0x4_property_map_read_u64) +- [Function `read_u128`](#0x4_property_map_read_u128) +- [Function `read_u256`](#0x4_property_map_read_u256) +- [Function `read_address`](#0x4_property_map_read_address) +- [Function `read_bytes`](#0x4_property_map_read_bytes) +- [Function `read_string`](#0x4_property_map_read_string) +- [Function `add`](#0x4_property_map_add) +- [Function `add_typed`](#0x4_property_map_add_typed) +- [Function `add_internal`](#0x4_property_map_add_internal) +- [Function `update`](#0x4_property_map_update) +- [Function `update_typed`](#0x4_property_map_update_typed) +- [Function `update_internal`](#0x4_property_map_update_internal) +- [Function `remove`](#0x4_property_map_remove) + + +<pre><code><b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/bcs.md#0x1_bcs">0x1::bcs</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error">0x1::error</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs">0x1::from_bcs</a>; +<b>use</b> <a href="../../aptos-framework/doc/object.md#0x1_object">0x1::object</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map">0x1::simple_map</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string">0x1::string</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/doc/type_info.md#0x1_type_info">0x1::type_info</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">0x1::vector</a>; +</code></pre> + + + +<a name="0x4_property_map_PropertyMap"></a> + +## Resource `PropertyMap` + + + +<pre><code><b>struct</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> <b>has</b> drop, key +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>inner: <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_SimpleMap">simple_map::SimpleMap</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, <a href="property_map.md#0x4_property_map_PropertyValue">property_map::PropertyValue</a>></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="0x4_property_map_PropertyValue"></a> + +## Struct `PropertyValue` + + + +<pre><code><b>struct</b> <a href="property_map.md#0x4_property_map_PropertyValue">PropertyValue</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>type: u8</code> +</dt> +<dd> + +</dd> +<dt> +<code>value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="0x4_property_map_MutatorRef"></a> + +## Struct `MutatorRef` + + + +<pre><code><b>struct</b> <a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>self: <b>address</b></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="@Constants_0"></a> + +## Constants + + +<a name="0x4_property_map_ETYPE_MISMATCH"></a> + +Property type does not match + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_ETYPE_MISMATCH">ETYPE_MISMATCH</a>: u64 = 5; +</code></pre> + + + +<a name="0x4_property_map_ADDRESS"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_ADDRESS">ADDRESS</a>: u8 = 7; +</code></pre> + + + +<a name="0x4_property_map_BOOL"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_BOOL">BOOL</a>: u8 = 0; +</code></pre> + + + +<a name="0x4_property_map_BYTE_VECTOR"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_BYTE_VECTOR">BYTE_VECTOR</a>: u8 = 8; +</code></pre> + + + +<a name="0x4_property_map_EKEY_AREADY_EXIST_IN_PROPERTY_MAP"></a> + +The property key already exists + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_EKEY_AREADY_EXIST_IN_PROPERTY_MAP">EKEY_AREADY_EXIST_IN_PROPERTY_MAP</a>: u64 = 1; +</code></pre> + + + +<a name="0x4_property_map_EKEY_TYPE_COUNT_MISMATCH"></a> + +Property key and type count do not match + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_EKEY_TYPE_COUNT_MISMATCH">EKEY_TYPE_COUNT_MISMATCH</a>: u64 = 4; +</code></pre> + + + +<a name="0x4_property_map_EKEY_VALUE_COUNT_MISMATCH"></a> + +Property key and value counts do not match + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_EKEY_VALUE_COUNT_MISMATCH">EKEY_VALUE_COUNT_MISMATCH</a>: u64 = 3; +</code></pre> + + + +<a name="0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST"></a> + +The property map does not exist within global storage + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST">EPROPERTY_MAP_DOES_NOT_EXIST</a>: u64 = 7; +</code></pre> + + + +<a name="0x4_property_map_EPROPERTY_MAP_NAME_TOO_LONG"></a> + +The name (key) of the property is too long + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_EPROPERTY_MAP_NAME_TOO_LONG">EPROPERTY_MAP_NAME_TOO_LONG</a>: u64 = 6; +</code></pre> + + + +<a name="0x4_property_map_EPROPERTY_NUMBER_EXCEEDS_LIMIT"></a> + +The number of property exceeds the limit + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_EPROPERTY_NUMBER_EXCEEDS_LIMIT">EPROPERTY_NUMBER_EXCEEDS_LIMIT</a>: u64 = 2; +</code></pre> + + + +<a name="0x4_property_map_ETYPE_INVALID"></a> + +Invalid type specified + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_ETYPE_INVALID">ETYPE_INVALID</a>: u64 = 8; +</code></pre> + + + +<a name="0x4_property_map_MAX_PROPERTY_MAP_SIZE"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_MAX_PROPERTY_MAP_SIZE">MAX_PROPERTY_MAP_SIZE</a>: u64 = 1000; +</code></pre> + + + +<a name="0x4_property_map_MAX_PROPERTY_NAME_LENGTH"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_MAX_PROPERTY_NAME_LENGTH">MAX_PROPERTY_NAME_LENGTH</a>: u64 = 128; +</code></pre> + + + +<a name="0x4_property_map_STRING"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_STRING">STRING</a>: u8 = 9; +</code></pre> + + + +<a name="0x4_property_map_U128"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_U128">U128</a>: u8 = 5; +</code></pre> + + + +<a name="0x4_property_map_U16"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_U16">U16</a>: u8 = 2; +</code></pre> + + + +<a name="0x4_property_map_U256"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_U256">U256</a>: u8 = 6; +</code></pre> + + + +<a name="0x4_property_map_U32"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_U32">U32</a>: u8 = 3; +</code></pre> + + + +<a name="0x4_property_map_U64"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_U64">U64</a>: u8 = 4; +</code></pre> + + + +<a name="0x4_property_map_U8"></a> + + + +<pre><code><b>const</b> <a href="property_map.md#0x4_property_map_U8">U8</a>: u8 = 1; +</code></pre> + + + +<a name="0x4_property_map_init"></a> + +## Function `init` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_init">init</a>(ref: &<a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a>, container: <a href="property_map.md#0x4_property_map_PropertyMap">property_map::PropertyMap</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_init">init</a>(ref: &ConstructorRef, container: <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>) { + <b>let</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a> = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_signer">object::generate_signer</a>(ref); + <b>move_to</b>(&<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, container); +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_burn"></a> + +## Function `burn` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_burn">burn</a>(ref: <a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_burn">burn</a>(ref: <a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>move_from</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(ref.self); +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_prepare_input"></a> + +## Function `prepare_input` + +Helper for external entry functions to produce a valid container for property values. + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_prepare_input">prepare_input</a>(keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>>, values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>): <a href="property_map.md#0x4_property_map_PropertyMap">property_map::PropertyMap</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_prepare_input">prepare_input</a>( + keys: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + types: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><String>, + values: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>, +): <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> length = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_length">vector::length</a>(&keys); + <b>assert</b>!(<a href="property_map.md#0x4_property_map_length">length</a> <= <a href="property_map.md#0x4_property_map_MAX_PROPERTY_MAP_SIZE">MAX_PROPERTY_MAP_SIZE</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_invalid_argument">error::invalid_argument</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_NUMBER_EXCEEDS_LIMIT">EPROPERTY_NUMBER_EXCEEDS_LIMIT</a>)); + <b>assert</b>!(length == <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_length">vector::length</a>(&values), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_invalid_argument">error::invalid_argument</a>(<a href="property_map.md#0x4_property_map_EKEY_VALUE_COUNT_MISMATCH">EKEY_VALUE_COUNT_MISMATCH</a>)); + <b>assert</b>!(length == <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_length">vector::length</a>(&types), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_invalid_argument">error::invalid_argument</a>(<a href="property_map.md#0x4_property_map_EKEY_TYPE_COUNT_MISMATCH">EKEY_TYPE_COUNT_MISMATCH</a>)); + + <b>let</b> container = <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_create">simple_map::create</a><String, <a href="property_map.md#0x4_property_map_PropertyValue">PropertyValue</a>>(); + <b>while</b> (!<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_is_empty">vector::is_empty</a>(&keys)) { + <b>let</b> key = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_pop_back">vector::pop_back</a>(&<b>mut</b> keys); + <b>assert</b>!( + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_length">string::length</a>(&key) <= <a href="property_map.md#0x4_property_map_MAX_PROPERTY_NAME_LENGTH">MAX_PROPERTY_NAME_LENGTH</a>, + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_invalid_argument">error::invalid_argument</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_MAP_NAME_TOO_LONG">EPROPERTY_MAP_NAME_TOO_LONG</a>), + ); + + <b>let</b> value = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_pop_back">vector::pop_back</a>(&<b>mut</b> values); + <b>let</b> type = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_pop_back">vector::pop_back</a>(&<b>mut</b> types); + + <b>let</b> new_type = to_internal_type(type); + validate_type(new_type, value); + + <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_add">simple_map::add</a>(&<b>mut</b> container, key, <a href="property_map.md#0x4_property_map_PropertyValue">PropertyValue</a> { value, type: new_type }); + }; + + <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { inner: container } +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_generate_mutator_ref"></a> + +## Function `generate_mutator_ref` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_generate_mutator_ref">generate_mutator_ref</a>(ref: &<a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a>): <a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_generate_mutator_ref">generate_mutator_ref</a>(ref: &ConstructorRef): <a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a> { + <a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a> { self: <a href="../../aptos-framework/doc/object.md#0x1_object_address_from_constructor_ref">object::address_from_constructor_ref</a>(ref) } +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_contains_key"></a> + +## Function `contains_key` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_contains_key">contains_key</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_contains_key">contains_key</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): bool <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>assert</b>!( + <b>exists</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(<a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>)), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST">EPROPERTY_MAP_DOES_NOT_EXIST</a>), + ); + <b>let</b> <a href="property_map.md#0x4_property_map">property_map</a> = <b>borrow_global</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(<a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>)); + <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_contains_key">simple_map::contains_key</a>(&<a href="property_map.md#0x4_property_map">property_map</a>.inner, key) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_length"></a> + +## Function `length` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_length">length</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): u64 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_length">length</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>): u64 <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>assert</b>!( + <b>exists</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(<a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>)), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST">EPROPERTY_MAP_DOES_NOT_EXIST</a>), + ); + <b>let</b> <a href="property_map.md#0x4_property_map">property_map</a> = <b>borrow_global</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(<a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>)); + <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_length">simple_map::length</a>(&<a href="property_map.md#0x4_property_map">property_map</a>.inner) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read"></a> + +## Function `read` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read">read</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read">read</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): (String, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>assert</b>!( + <b>exists</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(<a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>)), + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST">EPROPERTY_MAP_DOES_NOT_EXIST</a>), + ); + <b>let</b> <a href="property_map.md#0x4_property_map">property_map</a> = <b>borrow_global</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(<a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>)); + <b>let</b> property_value = <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_borrow">simple_map::borrow</a>(&<a href="property_map.md#0x4_property_map">property_map</a>.inner, key); + <b>let</b> new_type = to_external_type(property_value.type); + (new_type, property_value.value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_bool"></a> + +## Function `read_bool` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_bool">read_bool</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_bool">read_bool</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): bool <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, bool>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_bool">from_bcs::to_bool</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_u8"></a> + +## Function `read_u8` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u8">read_u8</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): u8 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u8">read_u8</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): u8 <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, u8>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_u8">from_bcs::to_u8</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_u16"></a> + +## Function `read_u16` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u16">read_u16</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): u16 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u16">read_u16</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): u16 <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, u16>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_u16">from_bcs::to_u16</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_u32"></a> + +## Function `read_u32` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u32">read_u32</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): u32 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u32">read_u32</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): u32 <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, u32>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_u32">from_bcs::to_u32</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_u64"></a> + +## Function `read_u64` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u64">read_u64</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): u64 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u64">read_u64</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): u64 <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, u64>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_u64">from_bcs::to_u64</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_u128"></a> + +## Function `read_u128` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u128">read_u128</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): u128 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u128">read_u128</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): u128 <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, u128>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_u128">from_bcs::to_u128</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_u256"></a> + +## Function `read_u256` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u256">read_u256</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): u256 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_u256">read_u256</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): u256 <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, u256>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_u256">from_bcs::to_u256</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_address"></a> + +## Function `read_address` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_address">read_address</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <b>address</b> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_address">read_address</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): <b>address</b> <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, <b>address</b>>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_address">from_bcs::to_address</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_bytes"></a> + +## Function `read_bytes` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_bytes">read_bytes</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_bytes">read_bytes</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8><b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_bytes">from_bcs::to_bytes</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_read_string"></a> + +## Function `read_string` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_string">read_string</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &<a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_read_string">read_string</a><T: key>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>: &Object<T>, key: &String): String <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> value = read_typed<T, String>(<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>, key); + <a href="../../aptos-framework/../aptos-stdlib/doc/from_bcs.md#0x1_from_bcs_to_string">from_bcs::to_string</a>(value) +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_add"></a> + +## Function `add` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_add">add</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, type: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_add">add</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>, key: String, type: String, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> new_type = to_internal_type(type); + validate_type(new_type, value); + <a href="property_map.md#0x4_property_map_add_internal">add_internal</a>(ref, key, new_type, value); +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_add_typed"></a> + +## Function `add_typed` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_add_typed">add_typed</a><T: drop>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: T) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_add_typed">add_typed</a><T: drop>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>, key: String, value: T) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> type = type_info_to_internal_type<T>(); + <a href="property_map.md#0x4_property_map_add_internal">add_internal</a>(ref, key, type, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/bcs.md#0x1_bcs_to_bytes">bcs::to_bytes</a>(&value)); +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_add_internal"></a> + +## Function `add_internal` + + + +<pre><code><b>fun</b> <a href="property_map.md#0x4_property_map_add_internal">add_internal</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>, key: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, type: u8, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>fun</b> <a href="property_map.md#0x4_property_map_add_internal">add_internal</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>, key: String, type: u8, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>assert</b>!(<b>exists</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(ref.self), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST">EPROPERTY_MAP_DOES_NOT_EXIST</a>)); + <b>let</b> <a href="property_map.md#0x4_property_map">property_map</a> = <b>borrow_global_mut</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(ref.self); + <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_add">simple_map::add</a>(&<b>mut</b> <a href="property_map.md#0x4_property_map">property_map</a>.inner, key, <a href="property_map.md#0x4_property_map_PropertyValue">PropertyValue</a> { type, value }); +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_update"></a> + +## Function `update` + + + +<pre><code><b>public</b> <b>fun</b> <b>update</b>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, type: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <b>update</b>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>, key: &String, type: String, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> new_type = to_internal_type(type); + validate_type(new_type, value); + <a href="property_map.md#0x4_property_map_update_internal">update_internal</a>(ref, key, new_type, value); +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_update_typed"></a> + +## Function `update_typed` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_update_typed">update_typed</a><T: drop>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, value: T) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_update_typed">update_typed</a><T: drop>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>, key: &String, value: T) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>let</b> type = type_info_to_internal_type<T>(); + <a href="property_map.md#0x4_property_map_update_internal">update_internal</a>(ref, key, type, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/bcs.md#0x1_bcs_to_bytes">bcs::to_bytes</a>(&value)); +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_update_internal"></a> + +## Function `update_internal` + + + +<pre><code><b>fun</b> <a href="property_map.md#0x4_property_map_update_internal">update_internal</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, type: u8, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>fun</b> <a href="property_map.md#0x4_property_map_update_internal">update_internal</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>, key: &String, type: u8, value: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8>) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>assert</b>!(<b>exists</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(ref.self), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST">EPROPERTY_MAP_DOES_NOT_EXIST</a>)); + <b>let</b> <a href="property_map.md#0x4_property_map">property_map</a> = <b>borrow_global_mut</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(ref.self); + <b>let</b> old_value = <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_borrow_mut">simple_map::borrow_mut</a>(&<b>mut</b> <a href="property_map.md#0x4_property_map">property_map</a>.inner, key); + *old_value = <a href="property_map.md#0x4_property_map_PropertyValue">PropertyValue</a> { type, value }; +} +</code></pre> + + + +</details> + +<a name="0x4_property_map_remove"></a> + +## Function `remove` + + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_remove">remove</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">property_map::MutatorRef</a>, key: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="property_map.md#0x4_property_map_remove">remove</a>(ref: &<a href="property_map.md#0x4_property_map_MutatorRef">MutatorRef</a>, key: &String) <b>acquires</b> <a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a> { + <b>assert</b>!(<b>exists</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(ref.self), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="property_map.md#0x4_property_map_EPROPERTY_MAP_DOES_NOT_EXIST">EPROPERTY_MAP_DOES_NOT_EXIST</a>)); + <b>let</b> <a href="property_map.md#0x4_property_map">property_map</a> = <b>borrow_global_mut</b><<a href="property_map.md#0x4_property_map_PropertyMap">PropertyMap</a>>(ref.self); + <a href="../../aptos-framework/../aptos-stdlib/doc/simple_map.md#0x1_simple_map_remove">simple_map::remove</a>(&<b>mut</b> <a href="property_map.md#0x4_property_map">property_map</a>.inner, key); +} +</code></pre> + + + +</details> + + +[move-book]: https://move-language.github.io/move/introduction.html diff --git a/aptos-move/framework/aptos-token-objects/doc/royalty.md b/aptos-move/framework/aptos-token-objects/doc/royalty.md new file mode 100644 index 0000000000000..0736f4d912b38 --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc/royalty.md @@ -0,0 +1,393 @@ + +<a name="0x4_royalty"></a> + +# Module `0x4::royalty` + +This defines an object-based Royalty. The royalty can be applied to either a collection or a +token. Applications should read the royalty from the token, as it will read the appropriate +royalty. + + +- [Resource `Royalty`](#0x4_royalty_Royalty) +- [Struct `MutatorRef`](#0x4_royalty_MutatorRef) +- [Constants](#@Constants_0) +- [Function `init`](#0x4_royalty_init) +- [Function `update`](#0x4_royalty_update) +- [Function `create`](#0x4_royalty_create) +- [Function `generate_mutator_ref`](#0x4_royalty_generate_mutator_ref) +- [Function `exists_at`](#0x4_royalty_exists_at) +- [Function `delete`](#0x4_royalty_delete) +- [Function `get`](#0x4_royalty_get) +- [Function `denominator`](#0x4_royalty_denominator) +- [Function `numerator`](#0x4_royalty_numerator) +- [Function `payee_address`](#0x4_royalty_payee_address) + + +<pre><code><b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error">0x1::error</a>; +<b>use</b> <a href="../../aptos-framework/doc/object.md#0x1_object">0x1::object</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option">0x1::option</a>; +</code></pre> + + + +<a name="0x4_royalty_Royalty"></a> + +## Resource `Royalty` + +The royalty of a token within this collection -- this optional + + +<pre><code><b>struct</b> <a href="royalty.md#0x4_royalty_Royalty">Royalty</a> <b>has</b> <b>copy</b>, drop, key +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>numerator: u64</code> +</dt> +<dd> + +</dd> +<dt> +<code>denominator: u64</code> +</dt> +<dd> + +</dd> +<dt> +<code>payee_address: <b>address</b></code> +</dt> +<dd> + The recipient of royalty payments. See the <code>shared_account</code> for how to handle multiple + creators. +</dd> +</dl> + + +</details> + +<a name="0x4_royalty_MutatorRef"></a> + +## Struct `MutatorRef` + +This enables creating or overwriting a MutatorRef. + + +<pre><code><b>struct</b> <a href="royalty.md#0x4_royalty_MutatorRef">MutatorRef</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>inner: <a href="../../aptos-framework/doc/object.md#0x1_object_ExtendRef">object::ExtendRef</a></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="@Constants_0"></a> + +## Constants + + +<a name="0x4_royalty_EROYALTY_DENOMINATOR_IS_ZERO"></a> + + + +<pre><code><b>const</b> <a href="royalty.md#0x4_royalty_EROYALTY_DENOMINATOR_IS_ZERO">EROYALTY_DENOMINATOR_IS_ZERO</a>: u64 = 2; +</code></pre> + + + +<a name="0x4_royalty_EROYALTY_DOES_NOT_EXIST"></a> + + + +<pre><code><b>const</b> <a href="royalty.md#0x4_royalty_EROYALTY_DOES_NOT_EXIST">EROYALTY_DOES_NOT_EXIST</a>: u64 = 3; +</code></pre> + + + +<a name="0x4_royalty_EROYALTY_EXCEEDS_MAXIMUM"></a> + + + +<pre><code><b>const</b> <a href="royalty.md#0x4_royalty_EROYALTY_EXCEEDS_MAXIMUM">EROYALTY_EXCEEDS_MAXIMUM</a>: u64 = 1; +</code></pre> + + + +<a name="0x4_royalty_init"></a> + +## Function `init` + +Add a royalty, given a ConstructorRef. + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_init">init</a>(ref: &<a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a>, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_init">init</a>(ref: &ConstructorRef, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="royalty.md#0x4_royalty_Royalty">Royalty</a>) { + <b>let</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a> = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_signer">object::generate_signer</a>(ref); + <b>move_to</b>(&<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="royalty.md#0x4_royalty">royalty</a>); +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_update"></a> + +## Function `update` + +Set the royalty if it does not exist, replace it otherwise. + + +<pre><code><b>public</b> <b>fun</b> <b>update</b>(mutator_ref: &<a href="royalty.md#0x4_royalty_MutatorRef">royalty::MutatorRef</a>, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <b>update</b>(mutator_ref: &<a href="royalty.md#0x4_royalty_MutatorRef">MutatorRef</a>, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="royalty.md#0x4_royalty_Royalty">Royalty</a>) <b>acquires</b> <a href="royalty.md#0x4_royalty_Royalty">Royalty</a> { + <b>let</b> addr = <a href="../../aptos-framework/doc/object.md#0x1_object_address_from_extend_ref">object::address_from_extend_ref</a>(&mutator_ref.inner); + <b>if</b> (<b>exists</b><<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>>(addr)) { + <b>move_from</b><<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>>(addr); + }; + + <b>let</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a> = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_signer_for_extending">object::generate_signer_for_extending</a>(&mutator_ref.inner); + <b>move_to</b>(&<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, <a href="royalty.md#0x4_royalty">royalty</a>); +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_create"></a> + +## Function `create` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_create">create</a>(numerator: u64, denominator: u64, payee_address: <b>address</b>): <a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_create">create</a>(numerator: u64, denominator: u64, payee_address: <b>address</b>): <a href="royalty.md#0x4_royalty_Royalty">Royalty</a> { + <b>assert</b>!(denominator != 0, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_out_of_range">error::out_of_range</a>(<a href="royalty.md#0x4_royalty_EROYALTY_DENOMINATOR_IS_ZERO">EROYALTY_DENOMINATOR_IS_ZERO</a>)); + <b>assert</b>!(<a href="royalty.md#0x4_royalty_numerator">numerator</a> <= denominator, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_out_of_range">error::out_of_range</a>(<a href="royalty.md#0x4_royalty_EROYALTY_EXCEEDS_MAXIMUM">EROYALTY_EXCEEDS_MAXIMUM</a>)); + + <a href="royalty.md#0x4_royalty_Royalty">Royalty</a> { numerator, denominator, payee_address } +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_generate_mutator_ref"></a> + +## Function `generate_mutator_ref` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_generate_mutator_ref">generate_mutator_ref</a>(ref: <a href="../../aptos-framework/doc/object.md#0x1_object_ExtendRef">object::ExtendRef</a>): <a href="royalty.md#0x4_royalty_MutatorRef">royalty::MutatorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_generate_mutator_ref">generate_mutator_ref</a>(ref: ExtendRef): <a href="royalty.md#0x4_royalty_MutatorRef">MutatorRef</a> { + <a href="royalty.md#0x4_royalty_MutatorRef">MutatorRef</a> { inner: ref } +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_exists_at"></a> + +## Function `exists_at` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_exists_at">exists_at</a>(addr: <b>address</b>): bool +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_exists_at">exists_at</a>(addr: <b>address</b>): bool { + <b>exists</b><<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>>(addr) +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_delete"></a> + +## Function `delete` + + + +<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="royalty.md#0x4_royalty_delete">delete</a>(addr: <b>address</b>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b>(<b>friend</b>) <b>fun</b> <a href="royalty.md#0x4_royalty_delete">delete</a>(addr: <b>address</b>) <b>acquires</b> <a href="royalty.md#0x4_royalty_Royalty">Royalty</a> { + <b>assert</b>!(<b>exists</b><<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>>(addr), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error_not_found">error::not_found</a>(<a href="royalty.md#0x4_royalty_EROYALTY_DOES_NOT_EXIST">EROYALTY_DOES_NOT_EXIST</a>)); + <b>move_from</b><<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>>(addr); +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_get"></a> + +## Function `get` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_get">get</a><T: key>(maybe_royalty: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_get">get</a><T: key>(maybe_royalty: Object<T>): Option<<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>> <b>acquires</b> <a href="royalty.md#0x4_royalty_Royalty">Royalty</a> { + <b>let</b> obj_addr = <a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(&maybe_royalty); + <b>if</b> (<b>exists</b><<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>>(obj_addr)) { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(*<b>borrow_global</b><<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>>(obj_addr)) + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>() + } +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_denominator"></a> + +## Function `denominator` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_denominator">denominator</a>(<a href="royalty.md#0x4_royalty">royalty</a>: &<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>): u64 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_denominator">denominator</a>(<a href="royalty.md#0x4_royalty">royalty</a>: &<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>): u64 { + <a href="royalty.md#0x4_royalty">royalty</a>.denominator +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_numerator"></a> + +## Function `numerator` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_numerator">numerator</a>(<a href="royalty.md#0x4_royalty">royalty</a>: &<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>): u64 +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_numerator">numerator</a>(<a href="royalty.md#0x4_royalty">royalty</a>: &<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>): u64 { + <a href="royalty.md#0x4_royalty">royalty</a>.numerator +} +</code></pre> + + + +</details> + +<a name="0x4_royalty_payee_address"></a> + +## Function `payee_address` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_payee_address">payee_address</a>(<a href="royalty.md#0x4_royalty">royalty</a>: &<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>): <b>address</b> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty_payee_address">payee_address</a>(<a href="royalty.md#0x4_royalty">royalty</a>: &<a href="royalty.md#0x4_royalty_Royalty">Royalty</a>): <b>address</b> { + <a href="royalty.md#0x4_royalty">royalty</a>.payee_address +} +</code></pre> + + + +</details> + + +[move-book]: https://move-language.github.io/move/introduction.html diff --git a/aptos-move/framework/aptos-token-objects/doc/token.md b/aptos-move/framework/aptos-token-objects/doc/token.md new file mode 100644 index 0000000000000..bc204c4349caf --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc/token.md @@ -0,0 +1,790 @@ + +<a name="0x4_token"></a> + +# Module `0x4::token` + +This defines an object-based Token. The key differentiating features from the Aptos standard +token are: +* Decouple token ownership from token data. +* Explicit data model for token metadata via adjacent resources +* Extensible framework for tokens + +TODO: +* Update Object<T> to be a viable input as a transaction arg and then update all readers as view. + + +- [Resource `Token`](#0x4_token_Token) +- [Struct `BurnRef`](#0x4_token_BurnRef) +- [Struct `MutatorRef`](#0x4_token_MutatorRef) +- [Struct `MutationEvent`](#0x4_token_MutationEvent) +- [Constants](#@Constants_0) +- [Function `create`](#0x4_token_create) +- [Function `create_token_address`](#0x4_token_create_token_address) +- [Function `create_token_seed`](#0x4_token_create_token_seed) +- [Function `generate_mutator_ref`](#0x4_token_generate_mutator_ref) +- [Function `generate_burn_ref`](#0x4_token_generate_burn_ref) +- [Function `address_from_burn_ref`](#0x4_token_address_from_burn_ref) +- [Function `creator`](#0x4_token_creator) +- [Function `collection`](#0x4_token_collection) +- [Function `collection_object`](#0x4_token_collection_object) +- [Function `creation_name`](#0x4_token_creation_name) +- [Function `description`](#0x4_token_description) +- [Function `name`](#0x4_token_name) +- [Function `uri`](#0x4_token_uri) +- [Function `royalty`](#0x4_token_royalty) +- [Function `burn`](#0x4_token_burn) +- [Function `set_description`](#0x4_token_set_description) +- [Function `set_name`](#0x4_token_set_name) +- [Function `set_uri`](#0x4_token_set_uri) + + +<pre><code><b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/error.md#0x1_error">0x1::error</a>; +<b>use</b> <a href="../../aptos-framework/doc/event.md#0x1_event">0x1::event</a>; +<b>use</b> <a href="../../aptos-framework/doc/object.md#0x1_object">0x1::object</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option">0x1::option</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">0x1::signer</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string">0x1::string</a>; +<b>use</b> <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">0x1::vector</a>; +<b>use</b> <a href="collection.md#0x4_collection">0x4::collection</a>; +<b>use</b> <a href="royalty.md#0x4_royalty">0x4::royalty</a>; +</code></pre> + + + +<a name="0x4_token_Token"></a> + +## Resource `Token` + +Represents the common fields to all tokens. + + +<pre><code><b>struct</b> <a href="token.md#0x4_token_Token">Token</a> <b>has</b> key +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code><a href="collection.md#0x4_collection">collection</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><<a href="collection.md#0x4_collection_Collection">collection::Collection</a>></code> +</dt> +<dd> + The collection from which this token resides. +</dd> +<dt> +<code>collection_id: u64</code> +</dt> +<dd> + Unique identifier within the collection, optional, 0 means unassigned +</dd> +<dt> +<code>description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + A brief description of the token. +</dd> +<dt> +<code>name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + 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" +</dd> +<dt> +<code>creation_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>></code> +</dt> +<dd> + The creation name of the token. Since tokens are created with the name as part of the + object id generation. +</dd> +<dt> +<code>uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + 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? +</dd> +<dt> +<code>mutation_events: <a href="../../aptos-framework/doc/event.md#0x1_event_EventHandle">event::EventHandle</a><<a href="token.md#0x4_token_MutationEvent">token::MutationEvent</a>></code> +</dt> +<dd> + Emitted upon any mutation of the token. +</dd> +</dl> + + +</details> + +<a name="0x4_token_BurnRef"></a> + +## 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. + + +<pre><code><b>struct</b> <a href="token.md#0x4_token_BurnRef">BurnRef</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>inner: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="../../aptos-framework/doc/object.md#0x1_object_DeleteRef">object::DeleteRef</a>></code> +</dt> +<dd> + +</dd> +<dt> +<code>self: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<b>address</b>></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="0x4_token_MutatorRef"></a> + +## Struct `MutatorRef` + +This enables mutating descritpion and URI by higher level services. + + +<pre><code><b>struct</b> <a href="token.md#0x4_token_MutatorRef">MutatorRef</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>self: <b>address</b></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="0x4_token_MutationEvent"></a> + +## 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. + + +<pre><code><b>struct</b> <a href="token.md#0x4_token_MutationEvent">MutationEvent</a> <b>has</b> drop, store +</code></pre> + + + +<details> +<summary>Fields</summary> + + +<dl> +<dt> +<code>mutated_field_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a></code> +</dt> +<dd> + +</dd> +</dl> + + +</details> + +<a name="@Constants_0"></a> + +## Constants + + +<a name="0x4_token_EFIELD_NOT_MUTABLE"></a> + +Attempted to mutate an immutable field + + +<pre><code><b>const</b> <a href="token.md#0x4_token_EFIELD_NOT_MUTABLE">EFIELD_NOT_MUTABLE</a>: u64 = 3; +</code></pre> + + + +<a name="0x4_token_ENOT_CREATOR"></a> + +The provided signer is not the creator + + +<pre><code><b>const</b> <a href="token.md#0x4_token_ENOT_CREATOR">ENOT_CREATOR</a>: u64 = 2; +</code></pre> + + + +<a name="0x4_token_ETOKEN_DOES_NOT_EXIST"></a> + + + +<pre><code><b>const</b> <a href="token.md#0x4_token_ETOKEN_DOES_NOT_EXIST">ETOKEN_DOES_NOT_EXIST</a>: u64 = 1; +</code></pre> + + + +<a name="0x4_token_create"></a> + +## Function `create` + +Creates a new token object and returns the ConstructorRef for additional specialization. + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_create">create</a>(creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, collection_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, <a href="royalty.md#0x4_royalty">royalty</a>: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_create">create</a>( + creator: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer">signer</a>, + collection_name: String, + description: String, + name: String, + <a href="royalty.md#0x4_royalty">royalty</a>: Option<Royalty>, + uri: String, +): ConstructorRef { + <b>let</b> creator_address = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/signer.md#0x1_signer_address_of">signer::address_of</a>(creator); + <b>let</b> seed = <a href="token.md#0x4_token_create_token_seed">create_token_seed</a>(&collection_name, &name); + + <b>let</b> collection_addr = <a href="collection.md#0x4_collection_create_collection_address">collection::create_collection_address</a>(&creator_address, &collection_name); + <b>let</b> <a href="collection.md#0x4_collection">collection</a> = <a href="../../aptos-framework/doc/object.md#0x1_object_address_to_object">object::address_to_object</a><Collection>(collection_addr); + <b>let</b> id = <a href="collection.md#0x4_collection_increment_supply">collection::increment_supply</a>(&<a href="collection.md#0x4_collection">collection</a>); + + <b>let</b> constructor_ref = <a href="../../aptos-framework/doc/object.md#0x1_object_create_named_object">object::create_named_object</a>(creator, seed); + <b>let</b> object_signer = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_signer">object::generate_signer</a>(&constructor_ref); + + <b>let</b> <a href="token.md#0x4_token">token</a> = <a href="token.md#0x4_token_Token">Token</a> { + <a href="collection.md#0x4_collection">collection</a>, + collection_id: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_get_with_default">option::get_with_default</a>(&<b>mut</b> id, 0), + description, + name, + creation_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>(), + uri, + mutation_events: <a href="../../aptos-framework/doc/object.md#0x1_object_new_event_handle">object::new_event_handle</a>(&object_signer), + }; + <b>move_to</b>(&object_signer, <a href="token.md#0x4_token">token</a>); + + <b>if</b> (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&<a href="royalty.md#0x4_royalty">royalty</a>)) { + <a href="royalty.md#0x4_royalty_init">royalty::init</a>(&constructor_ref, <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_extract">option::extract</a>(&<b>mut</b> <a href="royalty.md#0x4_royalty">royalty</a>)) + }; + constructor_ref +} +</code></pre> + + + +</details> + +<a name="0x4_token_create_token_address"></a> + +## Function `create_token_address` + +Generates the collections address based upon the creators address and the collection's name + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_create_token_address">create_token_address</a>(creator: &<b>address</b>, <a href="collection.md#0x4_collection">collection</a>: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, name: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <b>address</b> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_create_token_address">create_token_address</a>(creator: &<b>address</b>, <a href="collection.md#0x4_collection">collection</a>: &String, name: &String): <b>address</b> { + <a href="../../aptos-framework/doc/object.md#0x1_object_create_object_address">object::create_object_address</a>(creator, <a href="token.md#0x4_token_create_token_seed">create_token_seed</a>(<a href="collection.md#0x4_collection">collection</a>, name)) +} +</code></pre> + + + +</details> + +<a name="0x4_token_create_token_seed"></a> + +## Function `create_token_seed` + +Named objects are derived from a seed, the collection's seed is its name. + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_create_token_seed">create_token_seed</a>(<a href="collection.md#0x4_collection">collection</a>: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>, name: &<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_create_token_seed">create_token_seed</a>(<a href="collection.md#0x4_collection">collection</a>: &String, name: &String): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector">vector</a><u8> { + <b>let</b> seed = *<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_bytes">string::bytes</a>(<a href="collection.md#0x4_collection">collection</a>); + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_append">vector::append</a>(&<b>mut</b> seed, b"::"); + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/vector.md#0x1_vector_append">vector::append</a>(&<b>mut</b> seed, *<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_bytes">string::bytes</a>(name)); + seed +} +</code></pre> + + + +</details> + +<a name="0x4_token_generate_mutator_ref"></a> + +## Function `generate_mutator_ref` + +Creates a MutatorRef, which gates the ability to mutate any fields that support mutation. + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_generate_mutator_ref">generate_mutator_ref</a>(ref: &<a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a>): <a href="token.md#0x4_token_MutatorRef">token::MutatorRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_generate_mutator_ref">generate_mutator_ref</a>(ref: &ConstructorRef): <a href="token.md#0x4_token_MutatorRef">MutatorRef</a> { + <b>let</b> <a href="../../aptos-framework/doc/object.md#0x1_object">object</a> = <a href="../../aptos-framework/doc/object.md#0x1_object_object_from_constructor_ref">object::object_from_constructor_ref</a><<a href="token.md#0x4_token_Token">Token</a>>(ref); + <a href="token.md#0x4_token_MutatorRef">MutatorRef</a> { self: <a href="../../aptos-framework/doc/object.md#0x1_object_object_address">object::object_address</a>(&<a href="../../aptos-framework/doc/object.md#0x1_object">object</a>) } +} +</code></pre> + + + +</details> + +<a name="0x4_token_generate_burn_ref"></a> + +## Function `generate_burn_ref` + +Creates a BurnRef, which gates the ability to burn the given token. + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_generate_burn_ref">generate_burn_ref</a>(ref: &<a href="../../aptos-framework/doc/object.md#0x1_object_ConstructorRef">object::ConstructorRef</a>): <a href="token.md#0x4_token_BurnRef">token::BurnRef</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_generate_burn_ref">generate_burn_ref</a>(ref: &ConstructorRef): <a href="token.md#0x4_token_BurnRef">BurnRef</a> { + <b>let</b> (inner, self) = <b>if</b> (<a href="../../aptos-framework/doc/object.md#0x1_object_can_generate_delete_ref">object::can_generate_delete_ref</a>(ref)) { + <b>let</b> delete_ref = <a href="../../aptos-framework/doc/object.md#0x1_object_generate_delete_ref">object::generate_delete_ref</a>(ref); + (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(delete_ref), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>()) + } <b>else</b> { + <b>let</b> addr = <a href="../../aptos-framework/doc/object.md#0x1_object_address_from_constructor_ref">object::address_from_constructor_ref</a>(ref); + (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_none">option::none</a>(), <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_some">option::some</a>(addr)) + }; + <a href="token.md#0x4_token_BurnRef">BurnRef</a> { self, inner } +} +</code></pre> + + + +</details> + +<a name="0x4_token_address_from_burn_ref"></a> + +## Function `address_from_burn_ref` + +Extracts the tokens address from a BurnRef. + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_address_from_burn_ref">address_from_burn_ref</a>(ref: &<a href="token.md#0x4_token_BurnRef">token::BurnRef</a>): <b>address</b> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_address_from_burn_ref">address_from_burn_ref</a>(ref: &<a href="token.md#0x4_token_BurnRef">BurnRef</a>): <b>address</b> { + <b>if</b> (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&ref.inner)) { + <a href="../../aptos-framework/doc/object.md#0x1_object_address_from_delete_ref">object::address_from_delete_ref</a>(<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&ref.inner)) + } <b>else</b> { + *<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&ref.self) + } +} +</code></pre> + + + +</details> + +<a name="0x4_token_creator"></a> + +## Function `creator` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_creator">creator</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <b>address</b> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_creator">creator</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): <b>address</b> <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + <a href="collection.md#0x4_collection_creator">collection::creator</a>(borrow(&<a href="token.md#0x4_token">token</a>).<a href="collection.md#0x4_collection">collection</a>) +} +</code></pre> + + + +</details> + +<a name="0x4_token_collection"></a> + +## Function `collection` + + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection">collection</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="collection.md#0x4_collection">collection</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): String <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + <a href="collection.md#0x4_collection_name">collection::name</a>(borrow(&<a href="token.md#0x4_token">token</a>).<a href="collection.md#0x4_collection">collection</a>) +} +</code></pre> + + + +</details> + +<a name="0x4_token_collection_object"></a> + +## Function `collection_object` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_collection_object">collection_object</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><<a href="collection.md#0x4_collection_Collection">collection::Collection</a>> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_collection_object">collection_object</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): Object<Collection> <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + borrow(&<a href="token.md#0x4_token">token</a>).<a href="collection.md#0x4_collection">collection</a> +} +</code></pre> + + + +</details> + +<a name="0x4_token_creation_name"></a> + +## Function `creation_name` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_creation_name">creation_name</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_creation_name">creation_name</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): String <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + <b>let</b> <a href="token.md#0x4_token">token</a> = borrow(&<a href="token.md#0x4_token">token</a>); + <b>if</b> (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&<a href="token.md#0x4_token">token</a>.creation_name)) { + *<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_borrow">option::borrow</a>(&<a href="token.md#0x4_token">token</a>.creation_name) + } <b>else</b> { + <a href="token.md#0x4_token">token</a>.name + } +} +</code></pre> + + + +</details> + +<a name="0x4_token_description"></a> + +## Function `description` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_description">description</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_description">description</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): String <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + borrow(&<a href="token.md#0x4_token">token</a>).description +} +</code></pre> + + + +</details> + +<a name="0x4_token_name"></a> + +## Function `name` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_name">name</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_name">name</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): String <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + borrow(&<a href="token.md#0x4_token">token</a>).name +} +</code></pre> + + + +</details> + +<a name="0x4_token_uri"></a> + +## Function `uri` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_uri">uri</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_uri">uri</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): String <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + borrow(&<a href="token.md#0x4_token">token</a>).uri +} +</code></pre> + + + +</details> + +<a name="0x4_token_royalty"></a> + +## Function `royalty` + + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty">royalty</a><T: key>(<a href="token.md#0x4_token">token</a>: <a href="../../aptos-framework/doc/object.md#0x1_object_Object">object::Object</a><T>): <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_Option">option::Option</a><<a href="royalty.md#0x4_royalty_Royalty">royalty::Royalty</a>> +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="royalty.md#0x4_royalty">royalty</a><T: key>(<a href="token.md#0x4_token">token</a>: Object<T>): Option<Royalty> <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + borrow(&<a href="token.md#0x4_token">token</a>); + <b>let</b> <a href="royalty.md#0x4_royalty">royalty</a> = <a href="royalty.md#0x4_royalty_get">royalty::get</a>(<a href="token.md#0x4_token">token</a>); + <b>if</b> (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&<a href="royalty.md#0x4_royalty">royalty</a>)) { + <a href="royalty.md#0x4_royalty">royalty</a> + } <b>else</b> { + <b>let</b> creator = <a href="token.md#0x4_token_creator">creator</a>(<a href="token.md#0x4_token">token</a>); + <b>let</b> collection_name = <a href="collection.md#0x4_collection">collection</a>(<a href="token.md#0x4_token">token</a>); + <b>let</b> collection_address = <a href="collection.md#0x4_collection_create_collection_address">collection::create_collection_address</a>(&creator, &collection_name); + <b>let</b> <a href="collection.md#0x4_collection">collection</a> = <a href="../../aptos-framework/doc/object.md#0x1_object_address_to_object">object::address_to_object</a><<a href="collection.md#0x4_collection_Collection">collection::Collection</a>>(collection_address); + <a href="royalty.md#0x4_royalty_get">royalty::get</a>(<a href="collection.md#0x4_collection">collection</a>) + } +} +</code></pre> + + + +</details> + +<a name="0x4_token_burn"></a> + +## Function `burn` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_burn">burn</a>(burn_ref: <a href="token.md#0x4_token_BurnRef">token::BurnRef</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_burn">burn</a>(burn_ref: <a href="token.md#0x4_token_BurnRef">BurnRef</a>) <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + <b>let</b> addr = <b>if</b> (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_some">option::is_some</a>(&burn_ref.inner)) { + <b>let</b> delete_ref = <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_extract">option::extract</a>(&<b>mut</b> burn_ref.inner); + <b>let</b> addr = <a href="../../aptos-framework/doc/object.md#0x1_object_address_from_delete_ref">object::address_from_delete_ref</a>(&delete_ref); + <a href="../../aptos-framework/doc/object.md#0x1_object_delete">object::delete</a>(delete_ref); + addr + } <b>else</b> { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_extract">option::extract</a>(&<b>mut</b> burn_ref.self) + }; + + <b>if</b> (<a href="royalty.md#0x4_royalty_exists_at">royalty::exists_at</a>(addr)) { + <a href="royalty.md#0x4_royalty_delete">royalty::delete</a>(addr) + }; + + <b>let</b> <a href="token.md#0x4_token_Token">Token</a> { + <a href="collection.md#0x4_collection">collection</a>, + collection_id: _, + description: _, + name: _, + creation_name: _, + uri: _, + mutation_events, + } = <b>move_from</b><<a href="token.md#0x4_token_Token">Token</a>>(addr); + + <a href="../../aptos-framework/doc/event.md#0x1_event_destroy_handle">event::destroy_handle</a>(mutation_events); + <a href="collection.md#0x4_collection_decrement_supply">collection::decrement_supply</a>(&<a href="collection.md#0x4_collection">collection</a>); +} +</code></pre> + + + +</details> + +<a name="0x4_token_set_description"></a> + +## Function `set_description` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_set_description">set_description</a>(mutator_ref: &<a href="token.md#0x4_token_MutatorRef">token::MutatorRef</a>, description: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_set_description">set_description</a>(mutator_ref: &<a href="token.md#0x4_token_MutatorRef">MutatorRef</a>, description: String) <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + <b>let</b> <a href="token.md#0x4_token">token</a> = borrow_mut(mutator_ref); + <a href="token.md#0x4_token">token</a>.description = description; + <a href="../../aptos-framework/doc/event.md#0x1_event_emit_event">event::emit_event</a>( + &<b>mut</b> <a href="token.md#0x4_token">token</a>.mutation_events, + <a href="token.md#0x4_token_MutationEvent">MutationEvent</a> { mutated_field_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_utf8">string::utf8</a>(b"description") }, + ); +} +</code></pre> + + + +</details> + +<a name="0x4_token_set_name"></a> + +## Function `set_name` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_set_name">set_name</a>(mutator_ref: &<a href="token.md#0x4_token_MutatorRef">token::MutatorRef</a>, name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_set_name">set_name</a>(mutator_ref: &<a href="token.md#0x4_token_MutatorRef">MutatorRef</a>, name: String) <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + <b>let</b> <a href="token.md#0x4_token">token</a> = borrow_mut(mutator_ref); + <b>if</b> (<a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_is_none">option::is_none</a>(&<a href="token.md#0x4_token">token</a>.creation_name)) { + <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/option.md#0x1_option_fill">option::fill</a>(&<b>mut</b> <a href="token.md#0x4_token">token</a>.creation_name, <a href="token.md#0x4_token">token</a>.name) + }; + <a href="token.md#0x4_token">token</a>.name = name; + <a href="../../aptos-framework/doc/event.md#0x1_event_emit_event">event::emit_event</a>( + &<b>mut</b> <a href="token.md#0x4_token">token</a>.mutation_events, + <a href="token.md#0x4_token_MutationEvent">MutationEvent</a> { mutated_field_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_utf8">string::utf8</a>(b"name") }, + ); +} +</code></pre> + + + +</details> + +<a name="0x4_token_set_uri"></a> + +## Function `set_uri` + + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_set_uri">set_uri</a>(mutator_ref: &<a href="token.md#0x4_token_MutatorRef">token::MutatorRef</a>, uri: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_String">string::String</a>) +</code></pre> + + + +<details> +<summary>Implementation</summary> + + +<pre><code><b>public</b> <b>fun</b> <a href="token.md#0x4_token_set_uri">set_uri</a>(mutator_ref: &<a href="token.md#0x4_token_MutatorRef">MutatorRef</a>, uri: String) <b>acquires</b> <a href="token.md#0x4_token_Token">Token</a> { + <b>let</b> <a href="token.md#0x4_token">token</a> = borrow_mut(mutator_ref); + <a href="token.md#0x4_token">token</a>.uri = uri; + <a href="../../aptos-framework/doc/event.md#0x1_event_emit_event">event::emit_event</a>( + &<b>mut</b> <a href="token.md#0x4_token">token</a>.mutation_events, + <a href="token.md#0x4_token_MutationEvent">MutationEvent</a> { mutated_field_name: <a href="../../aptos-framework/../aptos-stdlib/../move-stdlib/doc/string.md#0x1_string_utf8">string::utf8</a>(b"uri") }, + ); +} +</code></pre> + + + +</details> + + +[move-book]: https://move-language.github.io/move/introduction.html diff --git a/aptos-move/framework/aptos-token-objects/doc_template/overview.md b/aptos-move/framework/aptos-token-objects/doc_template/overview.md new file mode 100644 index 0000000000000..006db85f6117a --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc_template/overview.md @@ -0,0 +1,7 @@ +# Aptos Token Framework + +This is the reference documentation of the Aptos Token Objects framework. + +## Index + +> {{move-index}} diff --git a/aptos-move/framework/aptos-token-objects/doc_template/references.md b/aptos-move/framework/aptos-token-objects/doc_template/references.md new file mode 100644 index 0000000000000..147a67c84546c --- /dev/null +++ b/aptos-move/framework/aptos-token-objects/doc_template/references.md @@ -0,0 +1 @@ +[move-book]: https://move-language.github.io/move/introduction.html diff --git a/aptos-move/move-examples/token_objects/sources/aptos_token.move b/aptos-move/framework/aptos-token-objects/sources/aptos_token.move similarity index 79% rename from aptos-move/move-examples/token_objects/sources/aptos_token.move rename to aptos-move/framework/aptos-token-objects/sources/aptos_token.move index 09af3360cbc2f..92813f439f5c4 100644 --- a/aptos-move/move-examples/token_objects/sources/aptos_token.move +++ b/aptos-move/framework/aptos-token-objects/sources/aptos_token.move @@ -6,7 +6,7 @@ /// * Creator-based freezing of tokens /// * Standard object-based transfer and events /// * Metadata property type -module token_objects::aptos_token { +module aptos_token_objects::aptos_token { use std::error; use std::option::{Self, Option}; use std::string::String; @@ -14,10 +14,10 @@ module token_objects::aptos_token { use aptos_framework::object::{Self, ConstructorRef, Object}; - use token_objects::collection; - use token_objects::property_map; - use token_objects::royalty; - use token_objects::token; + use aptos_token_objects::collection; + use aptos_token_objects::property_map; + use aptos_token_objects::royalty; + use aptos_token_objects::token; // The token does not exist const ETOKEN_DOES_NOT_EXIST: u64 = 1; @@ -67,7 +67,7 @@ module token_objects::aptos_token { /// Used to mutate fields mutator_ref: Option<token::MutatorRef>, /// Used to mutate properties - property_mutator_ref: Option<property_map::MutatorRef>, + property_mutator_ref: property_map::MutatorRef, } /// Create a new collection @@ -231,17 +231,11 @@ module token_objects::aptos_token { option::none() }; - let property_mutator_ref = if (collection.mutable_token_properties) { - option::some(property_map::generate_mutator_ref(&constructor_ref)) - } else { - option::none() - }; - let aptos_token = AptosToken { burn_ref, transfer_ref: option::none(), mutator_ref, - property_mutator_ref, + property_mutator_ref: property_map::generate_mutator_ref(&constructor_ref), }; move_to(&object_signer, aptos_token); @@ -262,26 +256,33 @@ module token_objects::aptos_token { borrow_global<AptosToken>(token_address) } - public fun are_properties_mutable<T: key>(token: Object<T>): bool acquires AptosToken { - option::is_some(&borrow(&token).property_mutator_ref) + #[view] + public fun are_properties_mutable<T: key>(token: Object<T>): bool acquires AptosCollection { + let collection = token::collection_object(token); + borrow_collection(&collection).mutable_token_properties } + #[view] public fun is_burnable<T: key>(token: Object<T>): bool acquires AptosToken { option::is_some(&borrow(&token).burn_ref) } + #[view] public fun is_freezable_by_creator<T: key>(token: Object<T>): bool acquires AptosCollection { are_collection_tokens_freezable(token::collection_object(token)) } + #[view] public fun is_mutable_description<T: key>(token: Object<T>): bool acquires AptosCollection { is_mutable_collection_token_description(token::collection_object(token)) } + #[view] public fun is_mutable_name<T: key>(token: Object<T>): bool acquires AptosCollection { is_mutable_collection_token_name(token::collection_object(token)) } + #[view] public fun is_mutable_uri<T: key>(token: Object<T>): bool acquires AptosCollection { is_mutable_collection_token_uri(token::collection_object(token)) } @@ -302,7 +303,7 @@ module token_objects::aptos_token { borrow_global<AptosToken>(token_address) } - public fun burn<T: key>(creator: &signer, token: Object<T>) acquires AptosToken { + public entry fun burn<T: key>(creator: &signer, token: Object<T>) acquires AptosToken { let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( option::is_some(&aptos_token.burn_ref), @@ -314,30 +315,33 @@ module token_objects::aptos_token { burn_ref, transfer_ref: _, mutator_ref: _, - property_mutator_ref: _, + property_mutator_ref, } = aptos_token; + property_map::burn(property_mutator_ref); token::burn(option::extract(&mut burn_ref)); } - public fun freeze_transfer<T: key>(creator: &signer, token: Object<T>) acquires AptosCollection, AptosToken { + public entry fun freeze_transfer<T: key>(creator: &signer, token: Object<T>) acquires AptosCollection, AptosToken { + let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( - are_collection_tokens_freezable(token::collection_object(token)), + are_collection_tokens_freezable(token::collection_object(token)) + && option::is_some(&aptos_token.transfer_ref), error::permission_denied(EFIELD_NOT_MUTABLE), ); - let aptos_token = authorized_borrow(&token, signer::address_of(creator)); object::disable_ungated_transfer(option::borrow(&aptos_token.transfer_ref)); } - public fun unfreeze_transfer<T: key>(creator: &signer, token: Object<T>) acquires AptosCollection, AptosToken { + public entry fun unfreeze_transfer<T: key>(creator: &signer, token: Object<T>) acquires AptosCollection, AptosToken { + let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( - are_collection_tokens_freezable(token::collection_object(token)), + are_collection_tokens_freezable(token::collection_object(token)) + && option::is_some(&aptos_token.transfer_ref), error::permission_denied(EFIELD_NOT_MUTABLE), ); - let aptos_token = authorized_borrow(&token, signer::address_of(creator)); object::enable_ungated_transfer(option::borrow(&aptos_token.transfer_ref)); } - public fun set_description<T: key>( + public entry fun set_description<T: key>( creator: &signer, token: Object<T>, description: String, @@ -350,7 +354,7 @@ module token_objects::aptos_token { token::set_description(option::borrow(&aptos_token.mutator_ref), description); } - public fun set_name<T: key>( + public entry fun set_name<T: key>( creator: &signer, token: Object<T>, name: String, @@ -363,7 +367,7 @@ module token_objects::aptos_token { token::set_name(option::borrow(&aptos_token.mutator_ref), name); } - public fun set_uri<T: key>( + public entry fun set_uri<T: key>( creator: &signer, token: Object<T>, uri: String, @@ -376,212 +380,89 @@ module token_objects::aptos_token { token::set_uri(option::borrow(&aptos_token.mutator_ref), uri); } - public fun add_property<T: key>( + public entry fun add_property<T: key>( creator: &signer, token: Object<T>, key: String, type: String, value: vector<u8>, - ) acquires AptosToken { + ) acquires AptosCollection, AptosToken { let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( - option::is_some(&aptos_token.property_mutator_ref), + are_properties_mutable(token), error::permission_denied(EPROPERTIES_NOT_MUTABLE), ); - property_map::add( - option::borrow(&aptos_token.property_mutator_ref), - key, - type, - value, - ); + property_map::add(&aptos_token.property_mutator_ref, key, type, value); } - public fun add_typed_property<T: key, V: drop>( + public entry fun add_typed_property<T: key, V: drop>( creator: &signer, token: Object<T>, key: String, value: V, - ) acquires AptosToken { + ) acquires AptosCollection, AptosToken { let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( - option::is_some(&aptos_token.property_mutator_ref), + are_properties_mutable(token), error::permission_denied(EPROPERTIES_NOT_MUTABLE), ); - property_map::add_typed( - option::borrow(&aptos_token.property_mutator_ref), - key, - value, - ); + property_map::add_typed(&aptos_token.property_mutator_ref, key, value); } - public fun remove_property<T: key>(creator: &signer, token: Object<T>, key: &String) acquires AptosToken { + public entry fun remove_property<T: key>( + creator: &signer, + token: Object<T>, + key: String, + ) acquires AptosCollection, AptosToken { let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( - option::is_some(&aptos_token.property_mutator_ref), + are_properties_mutable(token), error::permission_denied(EPROPERTIES_NOT_MUTABLE), ); - property_map::remove(option::borrow(&aptos_token.property_mutator_ref), key); + property_map::remove(&aptos_token.property_mutator_ref, &key); } - public fun update_property<T: key>( + public entry fun update_property<T: key>( creator: &signer, token: Object<T>, - key: &String, + key: String, type: String, value: vector<u8>, - ) acquires AptosToken { + ) acquires AptosCollection, AptosToken { let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( - option::is_some(&aptos_token.property_mutator_ref), + are_properties_mutable(token), error::permission_denied(EPROPERTIES_NOT_MUTABLE), ); - property_map::update( - option::borrow(&aptos_token.property_mutator_ref), - key, - type, - value, - ); + property_map::update(&aptos_token.property_mutator_ref, &key, type, value); } - public fun update_typed_property<T: key, V: drop>( + public entry fun update_typed_property<T: key, V: drop>( creator: &signer, token: Object<T>, - key: &String, + key: String, value: V, - ) acquires AptosToken { + ) acquires AptosCollection, AptosToken { let aptos_token = authorized_borrow(&token, signer::address_of(creator)); assert!( - option::is_some(&aptos_token.property_mutator_ref), + are_properties_mutable(token), error::permission_denied(EPROPERTIES_NOT_MUTABLE), ); - property_map::update_typed( - option::borrow(&aptos_token.property_mutator_ref), - key, - value, - ); - } - - // Token entry functions - - inline fun token_object(creator: &signer, collection: &String, name: &String): Object<AptosToken> { - let token_addr = token::create_token_address(&signer::address_of(creator), collection, name); - object::address_to_object<AptosToken>(token_addr) - } - - entry fun burn_call( - creator: &signer, - collection: String, - name: String, - ) acquires AptosToken { - burn(creator, token_object(creator, &collection, &name)); - } - - entry fun freeze_transfer_call( - creator: &signer, - collection: String, - name: String, - ) acquires AptosCollection, AptosToken { - freeze_transfer(creator, token_object(creator, &collection, &name)); - } - - entry fun unfreeze_transfer_call( - creator: &signer, - collection: String, - name: String, - ) acquires AptosCollection, AptosToken { - unfreeze_transfer(creator, token_object(creator, &collection, &name)); - } - - entry fun set_description_call( - creator: &signer, - collection: String, - name: String, - description: String, - ) acquires AptosCollection, AptosToken { - set_description(creator, token_object(creator, &collection, &name), description); - } - - entry fun set_name_call( - creator: &signer, - collection: String, - original_name: String, - new_name: String, - ) acquires AptosCollection, AptosToken { - set_name(creator, token_object(creator, &collection, &original_name), new_name); - } - - entry fun set_uri_call( - creator: &signer, - collection: String, - name: String, - uri: String, - ) acquires AptosCollection, AptosToken { - set_uri(creator, token_object(creator, &collection, &name), uri); + property_map::update_typed(&aptos_token.property_mutator_ref, &key, value); } - entry fun add_property_call( - creator: &signer, - collection: String, - name: String, - key: String, - type: String, - value: vector<u8>, - ) acquires AptosToken { - let token = token_object(creator, &collection, &name); - add_property(creator, token, key, type, value); - } - - entry fun add_typed_property_call<T: drop>( - creator: &signer, - collection: String, - name: String, - key: String, - value: T, - ) acquires AptosToken { - let token = token_object(creator, &collection, &name); - add_typed_property(creator, token, key, value); - } - - entry fun remove_property_call( - creator: &signer, - collection: String, - name: String, - key: String, - ) acquires AptosToken { - let token = token_object(creator, &collection, &name); - remove_property(creator, token, &key); - } - - entry fun update_property_call( - creator: &signer, - collection: String, - name: String, - key: String, - type: String, - value: vector<u8>, - ) acquires AptosToken { - let token = token_object(creator, &collection, &name); - update_property(creator, token, &key, type, value); - } + // Collection accessors - entry fun update_typed_property_call<T: drop>( - creator: &signer, - collection: String, - name: String, - key: String, - value: T, - ) acquires AptosToken { - let token = token_object(creator, &collection, &name); - update_typed_property(creator, token, &key, value); + inline fun collection_object(creator: &signer, name: &String): Object<AptosCollection> { + let collection_addr = collection::create_collection_address(&signer::address_of(creator), name); + object::address_to_object<AptosCollection>(collection_addr) } - // Collection accessors - inline fun borrow_collection<T: key>(token: &Object<T>): &AptosCollection { let collection_address = object::object_address(token); assert!( @@ -660,7 +541,7 @@ module token_objects::aptos_token { borrow_global<AptosCollection>(collection_address) } - public fun set_collection_description<T: key>( + public entry fun set_collection_description<T: key>( creator: &signer, collection: Object<T>, description: String, @@ -686,55 +567,39 @@ module token_objects::aptos_token { royalty::update(option::borrow(&aptos_collection.royalty_mutator_ref), royalty); } - public fun set_collection_uri<T: key>( + entry fun set_collection_royalties_call<T: key>( creator: &signer, collection: Object<T>, - uri: String, - ) acquires AptosCollection { - let aptos_collection = authorized_borrow_collection(&collection, signer::address_of(creator)); - assert!( - aptos_collection.mutable_uri, - error::permission_denied(EFIELD_NOT_MUTABLE), - ); - collection::set_uri(option::borrow(&aptos_collection.mutator_ref), uri); - } - - // Collection entry functions - - inline fun collection_object(creator: &signer, name: &String): Object<AptosCollection> { - let collection_addr = collection::create_collection_address(&signer::address_of(creator), name); - object::address_to_object<AptosCollection>(collection_addr) - } - - entry fun set_collection_description_call( - creator: &signer, - collection: String, - description: String, - ) acquires AptosCollection { - set_collection_description(creator, collection_object(creator, &collection), description); - } - - entry fun set_collection_royalties_call( - creator: &signer, - collection: String, royalty_numerator: u64, royalty_denominator: u64, payee_address: address, ) acquires AptosCollection { let royalty = royalty::create(royalty_numerator, royalty_denominator, payee_address); - set_collection_royalties(creator, collection_object(creator, &collection), royalty); + set_collection_royalties(creator, collection, royalty); } - entry fun set_collection_uri_call( + public entry fun set_collection_uri<T: key>( creator: &signer, - collection: String, + collection: Object<T>, uri: String, ) acquires AptosCollection { - set_collection_uri(creator, collection_object(creator, &collection), uri); + let aptos_collection = authorized_borrow_collection(&collection, signer::address_of(creator)); + assert!( + aptos_collection.mutable_uri, + error::permission_denied(EFIELD_NOT_MUTABLE), + ); + collection::set_uri(option::borrow(&aptos_collection.mutator_ref), uri); } // Tests + #[test_only] + inline fun token_object(creator: &signer, collection: &String, name: &String): Object<AptosToken> { + let token_addr = token::create_token_address(&signer::address_of(creator), collection, name); + object::address_to_object<AptosToken>(token_addr) + } + + #[test_only] use std::string; @@ -787,7 +652,7 @@ module token_objects::aptos_token { create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); - freeze_transfer_call(creator, collection_name, token_name); + freeze_transfer(creator, token); object::transfer(creator, token, @0x345); } @@ -798,8 +663,8 @@ module token_objects::aptos_token { create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); - freeze_transfer_call(creator, collection_name, token_name); - unfreeze_transfer_call(creator, collection_name, token_name); + freeze_transfer(creator, token); + unfreeze_transfer(creator, token); object::transfer(creator, token, @0x345); } @@ -822,7 +687,7 @@ module token_objects::aptos_token { create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); - freeze_transfer_call(creator, collection_name, token_name); + freeze_transfer(creator, token); unfreeze_transfer(another, token); } @@ -836,7 +701,7 @@ module token_objects::aptos_token { let description = string::utf8(b"not"); assert!(token::description(token) != description, 0); - set_description_call(creator, collection_name, token_name, description); + set_description(creator, token, description); assert!(token::description(token) == description, 1); } @@ -847,9 +712,9 @@ module token_objects::aptos_token { let token_name = string::utf8(b"token name"); create_collection_helper(creator, collection_name, false); - mint_helper(creator, collection_name, token_name); + let token = mint_helper(creator, collection_name, token_name); - set_description_call(creator, collection_name, token_name, string::utf8(b"")); + set_description(creator, token, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -878,7 +743,7 @@ module token_objects::aptos_token { let name = string::utf8(b"not"); assert!(token::name(token) != name, 0); - set_name_call(creator, collection_name, token_name, name); + set_name(creator, token, name); assert!(token::name(token) == name, 1); } @@ -889,9 +754,9 @@ module token_objects::aptos_token { let token_name = string::utf8(b"token name"); create_collection_helper(creator, collection_name, false); - mint_helper(creator, collection_name, token_name); + let token = mint_helper(creator, collection_name, token_name); - set_name_call(creator, collection_name, token_name, string::utf8(b"")); + set_name(creator, token, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -920,7 +785,7 @@ module token_objects::aptos_token { let uri = string::utf8(b"not"); assert!(token::uri(token) != uri, 0); - set_uri_call(creator, collection_name, token_name, uri); + set_uri(creator, token, uri); assert!(token::uri(token) == uri, 1); } @@ -931,9 +796,9 @@ module token_objects::aptos_token { let token_name = string::utf8(b"token name"); create_collection_helper(creator, collection_name, false); - mint_helper(creator, collection_name, token_name); + let token = mint_helper(creator, collection_name, token_name); - set_uri_call(creator, collection_name, token_name, string::utf8(b"")); + set_uri(creator, token, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -953,7 +818,7 @@ module token_objects::aptos_token { } #[test(creator = @0x123)] - entry fun test_burnable(creator: &signer) acquires AptosCollection, AptosToken { + fun test_burnable(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); @@ -968,7 +833,7 @@ module token_objects::aptos_token { #[test(creator = @0x123)] #[expected_failure(abort_code = 0x50004, location = Self)] - entry fun test_not_burnable(creator: &signer) acquires AptosCollection, AptosToken { + fun test_not_burnable(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); @@ -980,7 +845,7 @@ module token_objects::aptos_token { #[test(creator = @0x123, noncreator = @0x456)] #[expected_failure(abort_code = 0x50002, location = Self)] - entry fun test_burn_non_creator( + fun test_burn_non_creator( creator: &signer, noncreator: &signer, ) acquires AptosCollection, AptosToken { @@ -999,7 +864,7 @@ module token_objects::aptos_token { let collection = create_collection_helper(creator, collection_name, true); let value = string::utf8(b"not"); assert!(collection::description(collection) != value, 0); - set_collection_description_call(creator, collection_name, value); + set_collection_description(creator, collection, value); assert!(collection::description(collection) == value, 1); } @@ -1007,8 +872,8 @@ module token_objects::aptos_token { #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_immutable_collection_description(creator: &signer) acquires AptosCollection { let collection_name = string::utf8(b"collection name"); - create_collection_helper(creator, collection_name, false); - set_collection_description_call(creator, collection_name, string::utf8(b"")); + let collection = create_collection_helper(creator, collection_name, false); + set_collection_description(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -1028,7 +893,7 @@ module token_objects::aptos_token { let collection = create_collection_helper(creator, collection_name, true); let value = string::utf8(b"not"); assert!(collection::uri(collection) != value, 0); - set_collection_uri_call(creator, collection_name, value); + set_collection_uri(creator, collection, value); assert!(collection::uri(collection) == value, 1); } @@ -1036,8 +901,8 @@ module token_objects::aptos_token { #[expected_failure(abort_code = 0x50003, location = Self)] fun test_set_immutable_collection_uri(creator: &signer) acquires AptosCollection { let collection_name = string::utf8(b"collection name"); - create_collection_helper(creator, collection_name, false); - set_collection_uri_call(creator, collection_name, string::utf8(b"")); + let collection = create_collection_helper(creator, collection_name, false); + set_collection_uri(creator, collection, string::utf8(b"")); } #[test(creator = @0x123, noncreator = @0x456)] @@ -1052,7 +917,7 @@ module token_objects::aptos_token { } #[test(creator = @0x123)] - entry fun test_property_add(creator: &signer) acquires AptosCollection, AptosToken { + fun test_property_add(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); let property_name = string::utf8(b"u8"); @@ -1060,26 +925,26 @@ module token_objects::aptos_token { create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); - add_property_call(creator, collection_name, token_name, property_name, property_type, vector [ 0x08 ]); + add_property(creator, token, property_name, property_type, vector [ 0x08 ]); assert!(property_map::read_u8(&token, &property_name) == 0x8, 0); } #[test(creator = @0x123)] - entry fun test_property_typed_add(creator: &signer) acquires AptosCollection, AptosToken { + fun test_property_typed_add(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); let property_name = string::utf8(b"u8"); create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); - add_typed_property_call<u8>(creator, collection_name, token_name, property_name, 0x8); + add_typed_property<AptosToken, u8>(creator, token, property_name, 0x8); assert!(property_map::read_u8(&token, &property_name) == 0x8, 0); } #[test(creator = @0x123)] - entry fun test_property_update(creator: &signer) acquires AptosCollection, AptosToken { + fun test_property_update(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); let property_name = string::utf8(b"bool"); @@ -1087,45 +952,45 @@ module token_objects::aptos_token { create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); - update_property_call(creator, collection_name, token_name, property_name, property_type, vector [ 0x00 ]); + update_property(creator, token, property_name, property_type, vector [ 0x00 ]); assert!(!property_map::read_bool(&token, &property_name), 0); } #[test(creator = @0x123)] - entry fun test_property_update_typed(creator: &signer) acquires AptosCollection, AptosToken { + fun test_property_update_typed(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); let property_name = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); - update_typed_property_call<bool>(creator, collection_name, token_name, property_name, false); + update_typed_property<AptosToken, bool>(creator, token, property_name, false); assert!(!property_map::read_bool(&token, &property_name), 0); } #[test(creator = @0x123)] - entry fun test_property_remove(creator: &signer) acquires AptosCollection, AptosToken { + fun test_property_remove(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); let property_name = string::utf8(b"bool"); create_collection_helper(creator, collection_name, true); - mint_helper(creator, collection_name, token_name); - remove_property_call(creator, collection_name, token_name, property_name); + let token = mint_helper(creator, collection_name, token_name); + remove_property(creator, token, property_name); } #[test(creator = @0x123)] - entry fun test_royalties(creator: &signer) acquires AptosCollection, AptosToken { + fun test_royalties(creator: &signer) acquires AptosCollection, AptosToken { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); - create_collection_helper(creator, collection_name, true); + let collection = create_collection_helper(creator, collection_name, true); let token = mint_helper(creator, collection_name, token_name); let royalty_before = option::extract(&mut token::royalty(token)); - set_collection_royalties_call(creator, collection_name, 2, 3, @0x444); + set_collection_royalties_call(creator, collection, 2, 3, @0x444); let royalty_after = option::extract(&mut token::royalty(token)); assert!(royalty_before != royalty_after, 0); } diff --git a/aptos-move/move-examples/token_objects/sources/collection.move b/aptos-move/framework/aptos-token-objects/sources/collection.move similarity index 89% rename from aptos-move/move-examples/token_objects/sources/collection.move rename to aptos-move/framework/aptos-token-objects/sources/collection.move index 2303659b6e86f..994f6eda46287 100644 --- a/aptos-move/move-examples/token_objects/sources/collection.move +++ b/aptos-move/framework/aptos-token-objects/sources/collection.move @@ -20,7 +20,7 @@ /// * Consider supporting changing the aspects of supply with the MutatorRef. /// * Add aggregator support when added to framework /// * Update Object<T> to be viable input as a transaction arg and then update all readers as view. -module token_objects::collection { +module aptos_token_objects::collection { use std::error; use std::option::{Self, Option}; use std::signer; @@ -29,9 +29,9 @@ module token_objects::collection { use aptos_framework::event; use aptos_framework::object::{Self, ConstructorRef, Object}; - use token_objects::royalty::{Self, Royalty}; + use aptos_token_objects::royalty::{Self, Royalty}; - friend token_objects::token; + friend aptos_token_objects::token; /// The collections supply is at its maximum amount const EEXCEEDS_MAX_SUPPLY: u64 = 1; @@ -54,17 +54,17 @@ module token_objects::collection { mutation_events: event::EventHandle<MutationEvent>, } + /// This enables mutating description and URI by higher level services. + struct MutatorRef has drop, store { + self: address, + } + /// 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 { mutated_field_name: String, } - /// This enables mutating description and URI by higher level services. - struct MutatorRef has drop, store { - self: address, - } - #[resource_group_member(group = aptos_framework::object::ObjectGroup)] /// Fixed supply tracker, this is useful for ensuring that a limited number of tokens are minted. struct FixedSupply has key { @@ -151,6 +151,9 @@ module token_objects::collection { royalty::init(&constructor_ref, option::extract(&mut royalty)) }; + let transfer_ref = object::generate_transfer_ref(&constructor_ref); + object::disable_ungated_transfer(&transfer_ref); + constructor_ref } @@ -192,48 +195,6 @@ module token_objects::collection { } } - /// Entry function for creating a collection - public entry fun create_collection( - creator: &signer, - description: String, - name: String, - uri: String, - max_supply: u64, - enable_royalty: bool, - royalty_numerator: u64, - royalty_denominator: u64, - royalty_payee_address: address, - ) { - let royalty = if (enable_royalty) { - option::some(royalty::create( - royalty_numerator, - royalty_denominator, - royalty_payee_address, - )) - } else { - option::none() - }; - - if (max_supply == 0) { - create_untracked_collection( - creator, - description, - name, - royalty, - uri, - ) - } else { - create_fixed_collection( - creator, - description, - max_supply, - name, - royalty, - uri, - ) - }; - } - /// Creates a MutatorRef, which gates the ability to mutate any fields that support mutation. public fun generate_mutator_ref(ref: &ConstructorRef): MutatorRef { let object = object::object_from_constructor_ref<Collection>(ref); @@ -292,10 +253,7 @@ module token_objects::collection { borrow_global_mut<Collection>(mutator_ref.self) } - public fun set_description( - mutator_ref: &MutatorRef, - description: String, - ) acquires Collection { + public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Collection { let collection = borrow_mut(mutator_ref); collection.description = description; event::emit_event( @@ -304,10 +262,7 @@ module token_objects::collection { ); } - public fun set_uri( - mutator_ref: &MutatorRef, - uri: String, - ) acquires Collection { + public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Collection { let collection = borrow_mut(mutator_ref); collection.uri = uri; event::emit_event( @@ -319,6 +274,7 @@ module token_objects::collection { // Tests #[test(creator = @0x123, trader = @0x456)] + #[expected_failure(abort_code = 0x50003, location = aptos_framework::object)] entry fun test_create_and_transfer(creator: &signer, trader: &signer) { let creator_address = signer::address_of(creator); let collection_name = string::utf8(b"collection name"); @@ -329,7 +285,6 @@ module token_objects::collection { ); assert!(object::owner(collection) == creator_address, 1); object::transfer(creator, collection, signer::address_of(trader)); - assert!(object::owner(collection) == signer::address_of(trader), 1); } #[test(creator = @0x123)] diff --git a/aptos-move/move-examples/token_objects/sources/property_map.move b/aptos-move/framework/aptos-token-objects/sources/property_map.move similarity index 98% rename from aptos-move/move-examples/token_objects/sources/property_map.move rename to aptos-move/framework/aptos-token-objects/sources/property_map.move index e5d34812f9a94..e9d0950983c27 100644 --- a/aptos-move/move-examples/token_objects/sources/property_map.move +++ b/aptos-move/framework/aptos-token-objects/sources/property_map.move @@ -1,7 +1,7 @@ /// PropertyMap provides generic metadata support for AptosToken. It is a specialization of /// SimpleMap that enforces strict typing with minimal storage use by using constant u64 to /// represent types and storing values in bcs format. -module token_objects::property_map { +module aptos_token_objects::property_map { use std::bcs; use std::vector; use std::error; @@ -35,6 +35,7 @@ module token_objects::property_map { const MAX_PROPERTY_MAP_SIZE: u64 = 1000; const MAX_PROPERTY_NAME_LENGTH: u64 = 128; + // PropertyValue::type const BOOL: u8 = 0; const U8: u8 = 1; const U16: u8 = 2; @@ -49,7 +50,7 @@ module token_objects::property_map { // Structs #[resource_group_member(group = aptos_framework::object::ObjectGroup)] - struct PropertyMap has key { + struct PropertyMap has drop, key { inner: SimpleMap<String, PropertyValue>, } @@ -67,6 +68,10 @@ module token_objects::property_map { move_to(&signer, container); } + public fun burn(ref: MutatorRef) acquires PropertyMap { + move_from<PropertyMap>(ref.self); + } + /// Helper for external entry functions to produce a valid container for property values. public fun prepare_input( keys: vector<String>, @@ -242,7 +247,7 @@ module token_objects::property_map { let (type, value) = read(object, key); assert!( type == type_info::type_name<V>(), - error::invalid_argument(ETYPE_INVALID), + error::invalid_argument(ETYPE_MISMATCH), ); value } @@ -580,7 +585,7 @@ module token_objects::property_map { } #[test(creator = @0x123)] - #[expected_failure(abort_code = 0x10008, location = Self)] + #[expected_failure(abort_code = 0x10005, location = Self)] fun test_invalid_read(creator: &signer) acquires PropertyMap { let constructor_ref = object::create_named_object(creator, b""); let object = object::object_from_constructor_ref<object::ObjectCore>(&constructor_ref); diff --git a/aptos-move/move-examples/token_objects/sources/royalty.move b/aptos-move/framework/aptos-token-objects/sources/royalty.move similarity index 97% rename from aptos-move/move-examples/token_objects/sources/royalty.move rename to aptos-move/framework/aptos-token-objects/sources/royalty.move index 5d1c47b0c4273..e27be8ad59483 100644 --- a/aptos-move/move-examples/token_objects/sources/royalty.move +++ b/aptos-move/framework/aptos-token-objects/sources/royalty.move @@ -1,13 +1,13 @@ /// This defines an object-based Royalty. The royalty can be applied to either a collection or a /// token. Applications should read the royalty from the token, as it will read the appropriate /// royalty. -module token_objects::royalty { +module aptos_token_objects::royalty { use std::error; use std::option::{Self, Option}; use aptos_framework::object::{Self, ConstructorRef, ExtendRef, Object}; - friend token_objects::token; + friend aptos_token_objects::token; // Enforce that the royalty is between 0 and 1 const EROYALTY_EXCEEDS_MAXIMUM: u64 = 1; @@ -26,6 +26,7 @@ module token_objects::royalty { payee_address: address, } + /// This enables creating or overwriting a MutatorRef. struct MutatorRef has drop, store { inner: ExtendRef, } diff --git a/aptos-move/move-examples/token_objects/sources/token.move b/aptos-move/framework/aptos-token-objects/sources/token.move similarity index 95% rename from aptos-move/move-examples/token_objects/sources/token.move rename to aptos-move/framework/aptos-token-objects/sources/token.move index 98398a318b026..1b4be5d1b27f7 100644 --- a/aptos-move/move-examples/token_objects/sources/token.move +++ b/aptos-move/framework/aptos-token-objects/sources/token.move @@ -6,7 +6,7 @@ /// /// TODO: /// * Update Object<T> to be a viable input as a transaction arg and then update all readers as view. -module token_objects::token { +module aptos_token_objects::token { use std::error; use std::option::{Self, Option}; use std::string::{Self, String}; @@ -16,8 +16,8 @@ module token_objects::token { use aptos_framework::event; use aptos_framework::object::{Self, ConstructorRef, Object}; - use token_objects::collection::{Self, Collection}; - use token_objects::royalty::{Self, Royalty}; + use aptos_token_objects::collection::{Self, Collection}; + use aptos_token_objects::royalty::{Self, Royalty}; // The token does not exist const ETOKEN_DOES_NOT_EXIST: u64 = 1; @@ -56,17 +56,17 @@ module token_objects::token { self: Option<address>, } + /// This enables mutating descritpion and URI by higher level services. + struct MutatorRef has drop, store { + self: address, + } + /// 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 { mutated_field_name: String, } - /// This enables mutating descritpion and URI by higher level services. - struct MutatorRef has drop, store { - self: address, - } - /// Creates a new token object and returns the ConstructorRef for additional specialization. public fun create( creator: &signer, @@ -239,10 +239,7 @@ module token_objects::token { collection::decrement_supply(&collection); } - public fun set_description( - mutator_ref: &MutatorRef, - description: String, - ) acquires Token { + public fun set_description(mutator_ref: &MutatorRef, description: String) acquires Token { let token = borrow_mut(mutator_ref); token.description = description; event::emit_event( @@ -251,10 +248,7 @@ module token_objects::token { ); } - public fun set_name( - mutator_ref: &MutatorRef, - name: String, - ) acquires Token { + public fun set_name(mutator_ref: &MutatorRef, name: String) acquires Token { let token = borrow_mut(mutator_ref); if (option::is_none(&token.creation_name)) { option::fill(&mut token.creation_name, token.name) @@ -266,10 +260,7 @@ module token_objects::token { ); } - public fun set_uri( - mutator_ref: &MutatorRef, - uri: String, - ) acquires Token { + public fun set_uri(mutator_ref: &MutatorRef, uri: String) acquires Token { let token = borrow_mut(mutator_ref); token.uri = uri; event::emit_event( @@ -302,16 +293,15 @@ module token_objects::token { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); - collection::create_collection( + let creator_address = signer::address_of(creator); + let expected_royalty = royalty::create(10, 1000, creator_address); + collection::create_fixed_collection( creator, string::utf8(b"collection description"), + 5, collection_name, + option::some(expected_royalty), string::utf8(b"collection uri"), - 5, - true, - 10, - 1000, - signer::address_of(creator), ); create( @@ -323,10 +313,8 @@ module token_objects::token { string::utf8(b"token uri"), ); - let creator_address = signer::address_of(creator); let token_addr = create_token_address(&creator_address, &collection_name, &token_name); let token = object::address_to_object<Token>(token_addr); - let expected_royalty = royalty::create(10, 1000, creator_address); assert!(option::some(expected_royalty) == royalty(token), 0); } @@ -359,7 +347,7 @@ module token_objects::token { } #[test(creator = @0x123)] - #[expected_failure(abort_code = 0x20001, location = token_objects::collection)] + #[expected_failure(abort_code = 0x20001, location = aptos_token_objects::collection)] fun test_too_many_tokens(creator: &signer) { let collection_name = string::utf8(b"collection name"); let token_name = string::utf8(b"token name"); @@ -484,16 +472,13 @@ module token_objects::token { #[test_only] fun create_collection_helper(creator: &signer, collection_name: String, max_supply: u64) { - collection::create_collection( + collection::create_fixed_collection( creator, string::utf8(b"collection description"), + max_supply, collection_name, + option::none(), string::utf8(b"collection uri"), - max_supply, - false, - 0, - 0, - signer::address_of(creator), ); } diff --git a/aptos-move/framework/cached-packages/src/aptos_token_objects_sdk_builder.rs b/aptos-move/framework/cached-packages/src/aptos_token_objects_sdk_builder.rs new file mode 100644 index 0000000000000..ee0982cfbf492 --- /dev/null +++ b/aptos-move/framework/cached-packages/src/aptos_token_objects_sdk_builder.rs @@ -0,0 +1,374 @@ +// Copyright © Aptos Foundation +// SPDX-License-Identifier: Apache-2.0 + +// This file was generated. Do not modify! +// +// To update this code, run: `cargo run --release -p framework`. + +// Conversion library between a structured representation of a Move script call (`ScriptCall`) and the +// standard BCS-compatible representation used in Aptos transactions (`Script`). +// +// This code was generated by compiling known Script interfaces ("ABIs") with the tool `aptos-sdk-builder`. + +#![allow(dead_code)] +#![allow(unused_imports)] +use aptos_types::{ + account_address::AccountAddress, + transaction::{EntryFunction, TransactionPayload}, +}; +use move_core_types::{ + ident_str, + language_storage::{ModuleId, TypeTag}, +}; + +type Bytes = Vec<u8>; + +/// Structured representation of a call into a known Move entry function. +/// ```ignore +/// impl EntryFunctionCall { +/// pub fn encode(self) -> TransactionPayload { .. } +/// pub fn decode(&TransactionPayload) -> Option<EntryFunctionCall> { .. } +/// } +/// ``` +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "fuzzing", derive(proptest_derive::Arbitrary))] +#[cfg_attr(feature = "fuzzing", proptest(no_params))] +pub enum EntryFunctionCall { + /// Create a new collection + AptosTokenCreateCollection { + description: Vec<u8>, + max_supply: u64, + name: Vec<u8>, + uri: Vec<u8>, + mutable_description: bool, + mutable_royalty: bool, + mutable_uri: bool, + mutable_token_description: bool, + mutable_token_name: bool, + mutable_token_properties: bool, + mutable_token_uri: bool, + tokens_burnable_by_creator: bool, + tokens_freezable_by_creator: bool, + royalty_numerator: u64, + royalty_denominator: u64, + }, + + /// With an existing collection, directly mint a viable token into the creators account. + AptosTokenMint { + collection: Vec<u8>, + description: Vec<u8>, + name: Vec<u8>, + uri: Vec<u8>, + property_keys: Vec<Vec<u8>>, + property_types: Vec<Vec<u8>>, + property_values: Vec<Vec<u8>>, + }, + + /// With an existing collection, directly mint a soul bound token into the recipient's account. + AptosTokenMintSoulBound { + collection: Vec<u8>, + description: Vec<u8>, + name: Vec<u8>, + uri: Vec<u8>, + property_keys: Vec<Vec<u8>>, + property_types: Vec<Vec<u8>>, + property_values: Vec<Vec<u8>>, + soul_bound_to: AccountAddress, + }, +} + +impl EntryFunctionCall { + /// Build an Aptos `TransactionPayload` from a structured object `EntryFunctionCall`. + pub fn encode(self) -> TransactionPayload { + use EntryFunctionCall::*; + match self { + AptosTokenCreateCollection { + description, + max_supply, + name, + uri, + mutable_description, + mutable_royalty, + mutable_uri, + mutable_token_description, + mutable_token_name, + mutable_token_properties, + mutable_token_uri, + tokens_burnable_by_creator, + tokens_freezable_by_creator, + royalty_numerator, + royalty_denominator, + } => aptos_token_create_collection( + description, + max_supply, + name, + uri, + mutable_description, + mutable_royalty, + mutable_uri, + mutable_token_description, + mutable_token_name, + mutable_token_properties, + mutable_token_uri, + tokens_burnable_by_creator, + tokens_freezable_by_creator, + royalty_numerator, + royalty_denominator, + ), + AptosTokenMint { + collection, + description, + name, + uri, + property_keys, + property_types, + property_values, + } => aptos_token_mint( + collection, + description, + name, + uri, + property_keys, + property_types, + property_values, + ), + AptosTokenMintSoulBound { + collection, + description, + name, + uri, + property_keys, + property_types, + property_values, + soul_bound_to, + } => aptos_token_mint_soul_bound( + collection, + description, + name, + uri, + property_keys, + property_types, + property_values, + soul_bound_to, + ), + } + } + + /// Try to recognize an Aptos `TransactionPayload` and convert it into a structured object `EntryFunctionCall`. + pub fn decode(payload: &TransactionPayload) -> Option<EntryFunctionCall> { + if let TransactionPayload::EntryFunction(script) = payload { + match SCRIPT_FUNCTION_DECODER_MAP.get(&format!( + "{}_{}", + script.module().name(), + script.function() + )) { + Some(decoder) => decoder(payload), + None => None, + } + } else { + None + } + } +} + +/// Create a new collection +pub fn aptos_token_create_collection( + description: Vec<u8>, + max_supply: u64, + name: Vec<u8>, + uri: Vec<u8>, + mutable_description: bool, + mutable_royalty: bool, + mutable_uri: bool, + mutable_token_description: bool, + mutable_token_name: bool, + mutable_token_properties: bool, + mutable_token_uri: bool, + tokens_burnable_by_creator: bool, + tokens_freezable_by_creator: bool, + royalty_numerator: u64, + royalty_denominator: u64, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, + ]), + ident_str!("aptos_token").to_owned(), + ), + ident_str!("create_collection").to_owned(), + vec![], + vec![ + bcs::to_bytes(&description).unwrap(), + bcs::to_bytes(&max_supply).unwrap(), + bcs::to_bytes(&name).unwrap(), + bcs::to_bytes(&uri).unwrap(), + bcs::to_bytes(&mutable_description).unwrap(), + bcs::to_bytes(&mutable_royalty).unwrap(), + bcs::to_bytes(&mutable_uri).unwrap(), + bcs::to_bytes(&mutable_token_description).unwrap(), + bcs::to_bytes(&mutable_token_name).unwrap(), + bcs::to_bytes(&mutable_token_properties).unwrap(), + bcs::to_bytes(&mutable_token_uri).unwrap(), + bcs::to_bytes(&tokens_burnable_by_creator).unwrap(), + bcs::to_bytes(&tokens_freezable_by_creator).unwrap(), + bcs::to_bytes(&royalty_numerator).unwrap(), + bcs::to_bytes(&royalty_denominator).unwrap(), + ], + )) +} + +/// With an existing collection, directly mint a viable token into the creators account. +pub fn aptos_token_mint( + collection: Vec<u8>, + description: Vec<u8>, + name: Vec<u8>, + uri: Vec<u8>, + property_keys: Vec<Vec<u8>>, + property_types: Vec<Vec<u8>>, + property_values: Vec<Vec<u8>>, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, + ]), + ident_str!("aptos_token").to_owned(), + ), + ident_str!("mint").to_owned(), + vec![], + vec![ + bcs::to_bytes(&collection).unwrap(), + bcs::to_bytes(&description).unwrap(), + bcs::to_bytes(&name).unwrap(), + bcs::to_bytes(&uri).unwrap(), + bcs::to_bytes(&property_keys).unwrap(), + bcs::to_bytes(&property_types).unwrap(), + bcs::to_bytes(&property_values).unwrap(), + ], + )) +} + +/// With an existing collection, directly mint a soul bound token into the recipient's account. +pub fn aptos_token_mint_soul_bound( + collection: Vec<u8>, + description: Vec<u8>, + name: Vec<u8>, + uri: Vec<u8>, + property_keys: Vec<Vec<u8>>, + property_types: Vec<Vec<u8>>, + property_values: Vec<Vec<u8>>, + soul_bound_to: AccountAddress, +) -> TransactionPayload { + TransactionPayload::EntryFunction(EntryFunction::new( + ModuleId::new( + AccountAddress::new([ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 4, + ]), + ident_str!("aptos_token").to_owned(), + ), + ident_str!("mint_soul_bound").to_owned(), + vec![], + vec![ + bcs::to_bytes(&collection).unwrap(), + bcs::to_bytes(&description).unwrap(), + bcs::to_bytes(&name).unwrap(), + bcs::to_bytes(&uri).unwrap(), + bcs::to_bytes(&property_keys).unwrap(), + bcs::to_bytes(&property_types).unwrap(), + bcs::to_bytes(&property_values).unwrap(), + bcs::to_bytes(&soul_bound_to).unwrap(), + ], + )) +} +mod decoder { + use super::*; + pub fn aptos_token_create_collection( + payload: &TransactionPayload, + ) -> Option<EntryFunctionCall> { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::AptosTokenCreateCollection { + description: bcs::from_bytes(script.args().get(0)?).ok()?, + max_supply: bcs::from_bytes(script.args().get(1)?).ok()?, + name: bcs::from_bytes(script.args().get(2)?).ok()?, + uri: bcs::from_bytes(script.args().get(3)?).ok()?, + mutable_description: bcs::from_bytes(script.args().get(4)?).ok()?, + mutable_royalty: bcs::from_bytes(script.args().get(5)?).ok()?, + mutable_uri: bcs::from_bytes(script.args().get(6)?).ok()?, + mutable_token_description: bcs::from_bytes(script.args().get(7)?).ok()?, + mutable_token_name: bcs::from_bytes(script.args().get(8)?).ok()?, + mutable_token_properties: bcs::from_bytes(script.args().get(9)?).ok()?, + mutable_token_uri: bcs::from_bytes(script.args().get(10)?).ok()?, + tokens_burnable_by_creator: bcs::from_bytes(script.args().get(11)?).ok()?, + tokens_freezable_by_creator: bcs::from_bytes(script.args().get(12)?).ok()?, + royalty_numerator: bcs::from_bytes(script.args().get(13)?).ok()?, + royalty_denominator: bcs::from_bytes(script.args().get(14)?).ok()?, + }) + } else { + None + } + } + + pub fn aptos_token_mint(payload: &TransactionPayload) -> Option<EntryFunctionCall> { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::AptosTokenMint { + collection: bcs::from_bytes(script.args().get(0)?).ok()?, + description: bcs::from_bytes(script.args().get(1)?).ok()?, + name: bcs::from_bytes(script.args().get(2)?).ok()?, + uri: bcs::from_bytes(script.args().get(3)?).ok()?, + property_keys: bcs::from_bytes(script.args().get(4)?).ok()?, + property_types: bcs::from_bytes(script.args().get(5)?).ok()?, + property_values: bcs::from_bytes(script.args().get(6)?).ok()?, + }) + } else { + None + } + } + + pub fn aptos_token_mint_soul_bound(payload: &TransactionPayload) -> Option<EntryFunctionCall> { + if let TransactionPayload::EntryFunction(script) = payload { + Some(EntryFunctionCall::AptosTokenMintSoulBound { + collection: bcs::from_bytes(script.args().get(0)?).ok()?, + description: bcs::from_bytes(script.args().get(1)?).ok()?, + name: bcs::from_bytes(script.args().get(2)?).ok()?, + uri: bcs::from_bytes(script.args().get(3)?).ok()?, + property_keys: bcs::from_bytes(script.args().get(4)?).ok()?, + property_types: bcs::from_bytes(script.args().get(5)?).ok()?, + property_values: bcs::from_bytes(script.args().get(6)?).ok()?, + soul_bound_to: bcs::from_bytes(script.args().get(7)?).ok()?, + }) + } else { + None + } + } +} + +type EntryFunctionDecoderMap = std::collections::HashMap< + String, + Box< + dyn Fn(&TransactionPayload) -> Option<EntryFunctionCall> + + std::marker::Sync + + std::marker::Send, + >, +>; + +static SCRIPT_FUNCTION_DECODER_MAP: once_cell::sync::Lazy<EntryFunctionDecoderMap> = + once_cell::sync::Lazy::new(|| { + let mut map: EntryFunctionDecoderMap = std::collections::HashMap::new(); + map.insert( + "aptos_token_create_collection".to_string(), + Box::new(decoder::aptos_token_create_collection), + ); + map.insert( + "aptos_token_mint".to_string(), + Box::new(decoder::aptos_token_mint), + ); + map.insert( + "aptos_token_mint_soul_bound".to_string(), + Box::new(decoder::aptos_token_mint_soul_bound), + ); + map + }); diff --git a/aptos-move/framework/src/aptos.rs b/aptos-move/framework/src/aptos.rs index 90616474e195e..845756d18fd24 100644 --- a/aptos-move/framework/src/aptos.rs +++ b/aptos-move/framework/src/aptos.rs @@ -67,6 +67,10 @@ impl ReleaseTarget { "aptos-token", Some("cached-packages/src/aptos_token_sdk_builder.rs"), ), + ( + "aptos-token-objects", + Some("cached-packages/src/aptos_token_objects_sdk_builder.rs"), + ), ]; // Currently we don't have experimental packages only included in particular targets. result @@ -168,12 +172,14 @@ static NAMED_ADDRESSES: Lazy<BTreeMap<String, NumericalAddress>> = Lazy::new(|| let mut result = BTreeMap::new(); let zero = NumericalAddress::parse_str("0x0").unwrap(); let one = NumericalAddress::parse_str("0x1").unwrap(); - let two = NumericalAddress::parse_str("0x2").unwrap(); + let three = NumericalAddress::parse_str("0x3").unwrap(); + let four = NumericalAddress::parse_str("0x4").unwrap(); let resources = NumericalAddress::parse_str("0xA550C18").unwrap(); result.insert("std".to_owned(), one); result.insert("aptos_std".to_owned(), one); result.insert("aptos_framework".to_owned(), one); - result.insert("aptos_token".to_owned(), two); + result.insert("aptos_token".to_owned(), three); + result.insert("aptos_token_objects".to_owned(), four); result.insert("core_resources".to_owned(), resources); result.insert("vm_reserved".to_owned(), zero); result diff --git a/aptos-move/framework/tests/move_unit_test.rs b/aptos-move/framework/tests/move_unit_test.rs index c8583531a88e0..f71d3b633e81c 100644 --- a/aptos-move/framework/tests/move_unit_test.rs +++ b/aptos-move/framework/tests/move_unit_test.rs @@ -66,3 +66,8 @@ fn move_stdlib_unit_tests() { fn move_token_unit_tests() { run_tests_for_pkg("aptos-token"); } + +#[test] +fn move_token_objects_unit_tests() { + run_tests_for_pkg("aptos-token-objects"); +} diff --git a/aptos-move/move-examples/token_objects/Move.toml b/aptos-move/move-examples/token_objects/Move.toml index 37d121899a9ad..b816afb63d495 100644 --- a/aptos-move/move-examples/token_objects/Move.toml +++ b/aptos-move/move-examples/token_objects/Move.toml @@ -7,3 +7,4 @@ token_objects = "_" [dependencies] AptosFramework = { local = "../../framework/aptos-framework" } +AptosTokenObjects = { local = "../../framework/aptos-token-objects" } diff --git a/aptos-move/move-examples/token_objects/sources/hero.move b/aptos-move/move-examples/token_objects/sources/hero.move index 5484ed4eebc16..b5f639a447550 100644 --- a/aptos-move/move-examples/token_objects/sources/hero.move +++ b/aptos-move/move-examples/token_objects/sources/hero.move @@ -6,8 +6,8 @@ module token_objects::hero { use aptos_framework::object::{Self, ConstructorRef, Object}; - use token_objects::collection; - use token_objects::token; + use aptos_token_objects::collection; + use aptos_token_objects::token; const ENOT_A_HERO: u64 = 1; const ENOT_A_WEAPON: u64 = 2; diff --git a/aptos-move/vm-genesis/src/lib.rs b/aptos-move/vm-genesis/src/lib.rs index 32dce2d4ee25b..518a90db83f4f 100644 --- a/aptos-move/vm-genesis/src/lib.rs +++ b/aptos-move/vm-genesis/src/lib.rs @@ -420,6 +420,7 @@ pub fn default_features() -> Vec<FeatureFlag> { FeatureFlag::MULTISIG_ACCOUNTS, FeatureFlag::DELEGATION_POOLS, FeatureFlag::ED25519_PUBKEY_VALIDATE_RETURN_FALSE_WRONG_LENGTH, + FeatureFlag::STRUCT_CONSTRUCTORS, ] } diff --git a/developer-docs-site/docs/guides/aptos-name-service-connector.md b/developer-docs-site/docs/guides/aptos-name-service-connector.md index cfe8d679207d7..5489a28956594 100644 --- a/developer-docs-site/docs/guides/aptos-name-service-connector.md +++ b/developer-docs-site/docs/guides/aptos-name-service-connector.md @@ -70,7 +70,7 @@ The `AptosNamesConnector` component supports both mainnet and testnet. To connec ## Example The following example shows how to use the `AptosNamesConnector` component in a React application: -<last image> +<last image /> - Add a ‘claim name’ button to any page in your application. This allows your users to directly create an Aptos name, giving them a human-readable .apt name for their Aptos wallet address. You can customize the look of the button to suit your application. Here is an example on the profile page of an NFT marketplace. diff --git a/ecosystem/python/sdk/aptos_sdk/account_address.py b/ecosystem/python/sdk/aptos_sdk/account_address.py index 4ca2049f52239..db49df3675d36 100644 --- a/ecosystem/python/sdk/aptos_sdk/account_address.py +++ b/ecosystem/python/sdk/aptos_sdk/account_address.py @@ -4,12 +4,20 @@ from __future__ import annotations import hashlib -from typing import List +import unittest from . import ed25519 from .bcs import Deserializer, Serializer +class AuthKeyScheme: + Ed25519: bytes = b"\x00" + MultiEd25519: bytes = b"\x01" + DeriveObjectAddressFromGuid: bytes = b"\xFD" + DeriveObjectAddressFromSeed: bytes = b"\xFE" + DeriveResourceAccountAddress: bytes = b"\xFF" + + class AccountAddress: address: bytes LENGTH: int = 32 @@ -47,15 +55,48 @@ def from_hex(address: str) -> AccountAddress: @staticmethod def from_key(key: ed25519.PublicKey) -> AccountAddress: hasher = hashlib.sha3_256() - hasher.update(key.key.encode() + b"\x00") + hasher.update(key.key.encode()) + hasher.update(AuthKeyScheme.Ed25519) + return AccountAddress(hasher.digest()) + + @staticmethod + def from_multi_ed25519(keys: ed25519.MultiPublicKey) -> AccountAddress: + hasher = hashlib.sha3_256() + hasher.update(keys.to_bytes()) + hasher.update(AuthKeyScheme.MultiEd25519) + return AccountAddress(hasher.digest()) + + @staticmethod + def for_resource_account(creator: AccountAddress, seed: bytes) -> AccountAddress: + hasher = hashlib.sha3_256() + hasher.update(creator.address) + hasher.update(seed) + hasher.update(AuthKeyScheme.DeriveResourceAccountAddress) return AccountAddress(hasher.digest()) @staticmethod - def from_multisig_schema( - keys: List[ed25519.PublicKey], threshold: int + def for_named_object(creator: AccountAddress, seed: bytes) -> AccountAddress: + hasher = hashlib.sha3_256() + hasher.update(creator.address) + hasher.update(seed) + hasher.update(AuthKeyScheme.DeriveObjectAddressFromSeed) + return AccountAddress(hasher.digest()) + + @staticmethod + def for_named_token( + creator: AccountAddress, collection_name: str, token_name: str ) -> AccountAddress: - multisig_public_key = ed25519.MultiEd25519PublicKey(keys, threshold) - return AccountAddress(multisig_public_key.auth_key()) + collection_bytes = collection_name.encode() + token_bytes = token_name.encode() + return AccountAddress.for_named_object( + creator, collection_bytes + b"::" + token_bytes + ) + + @staticmethod + def for_named_collection( + creator: AccountAddress, collection_name: str + ) -> AccountAddress: + return AccountAddress.for_named_object(creator, collection_name.encode()) @staticmethod def deserialize(deserializer: Deserializer) -> AccountAddress: @@ -63,3 +104,56 @@ def deserialize(deserializer: Deserializer) -> AccountAddress: def serialize(self, serializer: Serializer): serializer.fixed_bytes(self.address) + + +class Test(unittest.TestCase): + def test_multi_ed25519(self): + private_key_1 = ed25519.PrivateKey.from_hex( + "4e5e3be60f4bbd5e98d086d932f3ce779ff4b58da99bf9e5241ae1212a29e5fe" + ) + private_key_2 = ed25519.PrivateKey.from_hex( + "1e70e49b78f976644e2c51754a2f049d3ff041869c669523ba95b172c7329901" + ) + multisig_public_key = ed25519.MultiPublicKey( + [private_key_1.public_key(), private_key_2.public_key()], 1 + ) + + expected = AccountAddress.from_hex( + "835bb8c5ee481062946b18bbb3b42a40b998d6bf5316ca63834c959dc739acf0" + ) + actual = AccountAddress.from_multi_ed25519(multisig_public_key) + self.assertEqual(actual, expected) + + def test_resource_account(self): + base_address = AccountAddress.from_hex("b0b") + expected = AccountAddress.from_hex( + "ee89f8c763c27f9d942d496c1a0dcf32d5eacfe78416f9486b8db66155b163b0" + ) + actual = AccountAddress.for_resource_account(base_address, b"\x0b\x00\x0b") + self.assertEqual(actual, expected) + + def test_named_object(self): + base_address = AccountAddress.from_hex("b0b") + expected = AccountAddress.from_hex( + "f417184602a828a3819edf5e36285ebef5e4db1ba36270be580d6fd2d7bcc321" + ) + actual = AccountAddress.for_named_object(base_address, b"bob's collection") + self.assertEqual(actual, expected) + + def test_collection(self): + base_address = AccountAddress.from_hex("b0b") + expected = AccountAddress.from_hex( + "f417184602a828a3819edf5e36285ebef5e4db1ba36270be580d6fd2d7bcc321" + ) + actual = AccountAddress.for_named_collection(base_address, "bob's collection") + self.assertEqual(actual, expected) + + def test_token(self): + base_address = AccountAddress.from_hex("b0b") + expected = AccountAddress.from_hex( + "e20d1f22a5400ba7be0f515b7cbd00edc42dbcc31acc01e31128b2b5ddb3c56e" + ) + actual = AccountAddress.for_named_token( + base_address, "bob's collection", "bob's token" + ) + self.assertEqual(actual, expected) diff --git a/ecosystem/python/sdk/aptos_sdk/aptos_token_client.py b/ecosystem/python/sdk/aptos_sdk/aptos_token_client.py new file mode 100644 index 0000000000000..0efb0036acb26 --- /dev/null +++ b/ecosystem/python/sdk/aptos_sdk/aptos_token_client.py @@ -0,0 +1,574 @@ +# Copyright © Aptos Foundation +# SPDX-License-Identifier: Apache-2.0 + +from __future__ import annotations + +from typing import Any, List, Optional, Tuple + +from .account import Account +from .account_address import AccountAddress +from .async_client import RestClient +from .bcs import Deserializer, Serializer +from .transactions import (EntryFunction, TransactionArgument, + TransactionPayload) +from .type_tag import StructTag, TypeTag + + +class Object: + + allow_ungated_transfer: bool + owner: AccountAddress + + struct_tag: str = "0x1::object::ObjectCore" + + def __init__(self, allow_ungated_transfer, owner): + self.allow_ungated_transfer = allow_ungated_transfer + self.owner = owner + + @staticmethod + def parse(resource: dict[str, Any]) -> Object: + return Object( + resource["allow_ungated_transfer"], + AccountAddress.from_hex(resource["owner"]), + ) + + def __str__(self) -> str: + return f"Object[allow_ungated_transfer: {self.allow_ungated_transfer}, owner: {self.owner}]" + + +class Collection: + + creator: AccountAddress + description: str + name: str + uri: str + + struct_tag: str = "0x4::collection::Collection" + + def __init__(self, creator, description, name, uri): + self.creator = creator + self.description = description + self.name = name + self.uri = uri + + def __str__(self) -> str: + return f"AccountAddress[creator: {self.creator}, description: {self.description}, name: {self.name}, ur: {self.uri}]" + + @staticmethod + def parse(resource: dict[str, Any]) -> Collection: + return Collection( + AccountAddress.from_hex(resource["creator"]), + resource["description"], + resource["name"], + resource["uri"], + ) + + +class Royalty: + + numerator: int + denominator: int + payee_address: AccountAddress + + struct_tag: str = "0x4::royalty::Royalty" + + def __init__(self, numerator, denominator, payee_address): + self.numerator = numerator + self.denominator = denominator + self.payee_address = payee_address + + def __str__(self) -> str: + return f"Royalty[numerator: {self.numerator}, denominator: {self.denominator}, payee_address: {self.payee_address}]" + + @staticmethod + def parse(resource: dict[str, Any]) -> Royalty: + return Royalty( + resource["numerator"], + resource["denominator"], + AccountAddress.from_hex(resource["payee_address"]), + ) + + +class Token: + + collection: AccountAddress + collection_id: int + creation_name: Optional[str] + description: str + name: str + uri: str + + struct_tag: str = "0x4::token::Token" + + def __init__( + self, + collection: AccountAddress, + collection_id: int, + creation_name: Optional[str], + description: str, + name: str, + uri: str, + ): + self.collection = collection + self.collection_id = collection_id + self.creation_name = creation_name + self.description = description + self.name = name + self.uri = uri + + def __str__(self) -> str: + return f"Token[collection: {self.collection}, collection_id: {self.collection_id}, creation_name: {self.creation_name}, description: {self.description}, name: {self.name}, uri: {self.uri}]" + + @staticmethod + def parse(resource: dict[str, Any]): + return Token( + AccountAddress.from_hex(resource["collection"]["inner"]), + int(resource["collection_id"]), + resource["creation_name"]["vec"][0] + if len(resource["creation_name"]["vec"]) == 1 + else None, + resource["description"], + resource["name"], + resource["uri"], + ) + + +class InvalidPropertyType(Exception): + """Invalid property type""" + + property_type: Any + + def __init__(self, property_type: Any): + message = f"Unknown property type: {property_type}" + super().__init__(message) + self.property_type = property_type + + +class Property: + + name: str + property_type: str + value: Any + + BOOL: int = 0 + U8: int = 1 + U16: int = 2 + U32: int = 3 + U64: int = 4 + U128: int = 5 + U256: int = 6 + ADDRESS: int = 7 + BYTE_VECTOR: int = 8 + STRING: int = 9 + + def __init__(self, name: str, property_type: str, value: Any): + self.name = name + self.property_type = property_type + self.value = value + + def __str__(self) -> str: + return f"Property[{self.name}, {self.property_type}, {self.value}]" + + def serialize_value(self) -> bytes: + ser = Serializer() + if self.property_type == "bool": + Serializer.bool(ser, self.value) + elif self.property_type == "u8": + Serializer.u8(ser, self.value) + elif self.property_type == "u16": + Serializer.u16(ser, self.value) + elif self.property_type == "u32": + Serializer.u32(ser, self.value) + elif self.property_type == "u64": + Serializer.u64(ser, self.value) + elif self.property_type == "u128": + Serializer.u128(ser, self.value) + elif self.property_type == "u256": + Serializer.u256(ser, self.value) + elif self.property_type == "address": + Serializer.struct(ser, self.value) + elif self.property_type == "0x1::string::String": + Serializer.str(ser, self.value) + elif self.property_type == "vector<u8>": + Serializer.to_bytes(ser, self.value) + else: + raise InvalidPropertyType(self.property_type) + return ser.output() + + def to_transaction_arguments(self) -> List[TransactionArgument]: + return [ + TransactionArgument(self.name, Serializer.str), + TransactionArgument(self.property_type, Serializer.str), + TransactionArgument(self.serialize_value(), Serializer.to_bytes), + ] + + @staticmethod + def parse(name: str, property_type: int, value: bytes) -> Property: + deserializer = Deserializer(value) + + if property_type == Property.BOOL: + return Property(name, "bool", deserializer.bool()) + elif property_type == Property.U8: + return Property(name, "u8", deserializer.u8()) + elif property_type == Property.U16: + return Property(name, "u16", deserializer.u16()) + elif property_type == Property.U32: + return Property(name, "u32", deserializer.u32()) + elif property_type == Property.U64: + return Property(name, "u64", deserializer.u64()) + elif property_type == Property.U128: + return Property(name, "u128", deserializer.u128()) + elif property_type == Property.U256: + return Property(name, "u256", deserializer.u256()) + elif property_type == Property.ADDRESS: + return Property(name, "address", AccountAddress.deserialize(deserializer)) + elif property_type == Property.STRING: + return Property(name, "0x1::string::String", deserializer.str()) + elif property_type == Property.BYTE_VECTOR: + return Property(name, "vector<u8>", deserializer.to_bytes()) + raise InvalidPropertyType(property_type) + + @staticmethod + def bool(name: str, value: bool) -> Property: + return Property(name, "bool", value) + + @staticmethod + def u8(name: str, value: int) -> Property: + return Property(name, "u8", value) + + @staticmethod + def u16(name: str, value: int) -> Property: + return Property(name, "u16", value) + + @staticmethod + def u32(name: str, value: int) -> Property: + return Property(name, "u32", value) + + @staticmethod + def u64(name: str, value: int) -> Property: + return Property(name, "u64", value) + + @staticmethod + def u128(name: str, value: int) -> Property: + return Property(name, "u128", value) + + @staticmethod + def u256(name: str, value: int) -> Property: + return Property(name, "u256", value) + + @staticmethod + def string(name: str, value: str) -> Property: + return Property(name, "0x1::string::String", value) + + @staticmethod + def bytes(name: str, value: bytes) -> Property: + return Property(name, "vector<u8>", value) + + +class PropertyMap: + + properties: List[Property] + + struct_tag: str = "0x4::property_map::PropertyMap" + + def __init__(self, properties: List[Property]): + self.properties = properties + + def __str__(self) -> str: + response = "PropertyMap[" + for prop in self.properties: + response += f"{prop}, " + if len(self.properties) > 0: + response = response[:-2] + response += "]" + return response + + def to_tuple(self) -> Tuple[List[str], List[str], List[bytes]]: + names = [] + types = [] + values = [] + + for prop in self.properties: + names.append(prop.name) + types.append(prop.property_type) + values.append(prop.serialize_value()) + + return (names, types, values) + + @staticmethod + def parse(resource: dict[str, Any]) -> PropertyMap: + props = resource["inner"]["data"] + properties = [] + for prop in props: + properties.append( + Property.parse( + prop["key"], + prop["value"]["type"], + bytes.fromhex(prop["value"]["value"][2:]), + ) + ) + + return PropertyMap(properties) + + +class ReadObject: + resource_map: dict[str, Any] = { + Collection.struct_tag: Collection, + Object.struct_tag: Object, + PropertyMap.struct_tag: PropertyMap, + Royalty.struct_tag: Royalty, + Token.struct_tag: Token, + } + + resources: dict[Any, Any] + + def __init__(self, resources: dict[Any, Any]): + self.resources = resources + + def __str__(self) -> str: + response = "ReadObject" + for (resource_obj, value) in self.resources.items(): + response += f"\n\t{resource_obj.struct_tag}: {value}" + + return response + + +class AptosTokenClient: + """A wrapper around reading and mutating AptosTokens also known as Token Objects""" + + client: RestClient + + def __init__(self, client: RestClient): + self.client = client + + async def read_object(self, address: AccountAddress) -> ReadObject: + resources = {} + + read_resources = await self.client.account_resources(address) + for resource in read_resources: + if resource["type"] in ReadObject.resource_map: + resource_obj = ReadObject.resource_map[resource["type"]] + resources[resource_obj] = resource_obj.parse(resource["data"]) + return ReadObject(resources) + + async def create_collection( + self, + creator: Account, + description: str, + max_supply: int, + name: str, + uri: str, + mutable_description: bool, + mutable_royalty: bool, + mutable_uri: bool, + mutable_token_description: bool, + mutable_token_name: bool, + mutable_token_properties: bool, + mutable_token_uri: bool, + tokens_burnable_by_creator: bool, + tokens_freezable_by_creator: bool, + royalty_numerator: int, + royalty_denominator: int, + ) -> str: + transaction_arguments = [ + TransactionArgument(description, Serializer.str), + TransactionArgument(max_supply, Serializer.u64), + TransactionArgument(name, Serializer.str), + TransactionArgument(uri, Serializer.str), + TransactionArgument(mutable_description, Serializer.bool), + TransactionArgument(mutable_royalty, Serializer.bool), + TransactionArgument(mutable_uri, Serializer.bool), + TransactionArgument(mutable_token_description, Serializer.bool), + TransactionArgument(mutable_token_name, Serializer.bool), + TransactionArgument(mutable_token_properties, Serializer.bool), + TransactionArgument(mutable_token_uri, Serializer.bool), + TransactionArgument(tokens_burnable_by_creator, Serializer.bool), + TransactionArgument(tokens_freezable_by_creator, Serializer.bool), + TransactionArgument(royalty_numerator, Serializer.u64), + TransactionArgument(royalty_denominator, Serializer.u64), + ] + + payload = EntryFunction.natural( + "0x4::aptos_token", + "create_collection", + [], + transaction_arguments, + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def mint_token( + self, + creator: Account, + collection: str, + description: str, + name: str, + uri: str, + properties: PropertyMap, + ) -> str: + (property_names, property_types, property_values) = properties.to_tuple() + transaction_arguments = [ + TransactionArgument(collection, Serializer.str), + TransactionArgument(description, Serializer.str), + TransactionArgument(name, Serializer.str), + TransactionArgument(uri, Serializer.str), + TransactionArgument( + property_names, Serializer.sequence_serializer(Serializer.str) + ), + TransactionArgument( + property_types, Serializer.sequence_serializer(Serializer.str) + ), + TransactionArgument( + property_values, Serializer.sequence_serializer(Serializer.to_bytes) + ), + ] + + payload = EntryFunction.natural( + "0x4::aptos_token", + "mint", + [], + transaction_arguments, + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def mint_soul_bound_token( + self, + creator: Account, + collection: str, + description: str, + name: str, + uri: str, + properties: PropertyMap, + soul_bound_to: AccountAddress, + ): + (property_names, property_types, property_values) = properties.to_tuple() + transaction_arguments = [ + TransactionArgument(collection, Serializer.str), + TransactionArgument(description, Serializer.str), + TransactionArgument(name, Serializer.str), + TransactionArgument(uri, Serializer.str), + TransactionArgument( + property_names, Serializer.sequence_serializer(Serializer.str) + ), + TransactionArgument( + property_types, Serializer.sequence_serializer(Serializer.str) + ), + TransactionArgument( + property_values, Serializer.sequence_serializer(Serializer.to_bytes) + ), + TransactionArgument(soul_bound_to, Serializer.struct), + ] + + payload = EntryFunction.natural( + "0x4::aptos_token", + "mint_soul_bound", + [], + transaction_arguments, + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def burn_token(self, creator: Account, token: AccountAddress) -> str: + payload = EntryFunction.natural( + "0x4::aptos_token", + "burn", + [TypeTag(StructTag.from_str("0x4::token::Token"))], + [TransactionArgument(token, Serializer.struct)], + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def freeze_token(self, creator: Account, token: AccountAddress) -> str: + payload = EntryFunction.natural( + "0x4::aptos_token", + "freeze_transfer", + [TypeTag(StructTag.from_str("0x4::token::Token"))], + [TransactionArgument(token, Serializer.struct)], + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def unfreeze_token(self, creator: Account, token: AccountAddress) -> str: + payload = EntryFunction.natural( + "0x4::aptos_token", + "unfreeze_transfer", + [TypeTag(StructTag.from_str("0x4::token::Token"))], + [TransactionArgument(token, Serializer.struct)], + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def add_token_property( + self, creator: Account, token: AccountAddress, prop: Property + ) -> str: + transaction_arguments = [TransactionArgument(token, Serializer.struct)] + transaction_arguments.extend(prop.to_transaction_arguments()) + + payload = EntryFunction.natural( + "0x4::aptos_token", + "add_property", + [TypeTag(StructTag.from_str("0x4::token::Token"))], + transaction_arguments, + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def remove_token_property( + self, creator: Account, token: AccountAddress, name: str + ) -> str: + transaction_arguments = [ + TransactionArgument(token, Serializer.struct), + TransactionArgument(name, Serializer.str), + ] + + payload = EntryFunction.natural( + "0x4::aptos_token", + "remove_property", + [TypeTag(StructTag.from_str("0x4::token::Token"))], + transaction_arguments, + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) + + async def update_token_property( + self, creator: Account, token: AccountAddress, prop: Property + ) -> str: + transaction_arguments = [TransactionArgument(token, Serializer.struct)] + transaction_arguments.extend(prop.to_transaction_arguments()) + + payload = EntryFunction.natural( + "0x4::aptos_token", + "update_property", + [TypeTag(StructTag.from_str("0x4::token::Token"))], + transaction_arguments, + ) + + signed_transaction = await self.client.create_bcs_signed_transaction( + creator, TransactionPayload(payload) + ) + return await self.client.submit_bcs_transaction(signed_transaction) diff --git a/ecosystem/python/sdk/aptos_sdk/async_client.py b/ecosystem/python/sdk/aptos_sdk/async_client.py index 6850307c18a6b..81d0c770baa3b 100644 --- a/ecosystem/python/sdk/aptos_sdk/async_client.py +++ b/ecosystem/python/sdk/aptos_sdk/async_client.py @@ -116,6 +116,23 @@ async def account_resource( raise ApiError(f"{response.text} - {account_address}", response.status_code) return response.json() + async def account_resources( + self, + account_address: AccountAddress, + ledger_version: int = None, + ) -> List[Dict[str, Any]]: + if not ledger_version: + request = f"{self.base_url}/accounts/{account_address}/resources" + else: + request = f"{self.base_url}/accounts/{account_address}/resources?ledger_version={ledger_version}" + + response = await self.client.get(request) + if response.status_code == 404: + raise AccountNotFound(f"{account_address}", account_address) + if response.status_code >= 400: + raise ApiError(f"{response.text} - {account_address}", response.status_code) + return response.json() + async def get_table_item( self, handle: str, @@ -729,15 +746,30 @@ async def fund_account(self, address: str, amount: int): class ApiError(Exception): """The API returned a non-success status code, e.g., >= 400""" + status_code: int + def __init__(self, message: str, status_code: int): # Call the base class constructor with the parameters it needs super().__init__(message) self.status_code = status_code +class AccountNotFound(Exception): + """The account was not found""" + + account: AccountAddress + + def __init__(self, message: str, account: AccountAddress): + # Call the base class constructor with the parameters it needs + super().__init__(message) + self.account = account + + class ResourceNotFound(Exception): """The underlying resource was not found""" + resource: str + def __init__(self, message: str, resource: str): # Call the base class constructor with the parameters it needs super().__init__(message) diff --git a/ecosystem/python/sdk/aptos_sdk/authenticator.py b/ecosystem/python/sdk/aptos_sdk/authenticator.py index ca83870ce0677..89998eb1e1c13 100644 --- a/ecosystem/python/sdk/aptos_sdk/authenticator.py +++ b/ecosystem/python/sdk/aptos_sdk/authenticator.py @@ -146,8 +146,8 @@ def serialize(self, serializer: Serializer): class MultiEd25519Authenticator: - public_key: ed25519.MultiEd25519PublicKey - signature: ed25519.MultiEd25519Signature + public_key: ed25519.MultiPublicKey + signature: ed25519.MultiSignature def __init__(self, public_key, signature): self.public_key = public_key diff --git a/ecosystem/python/sdk/aptos_sdk/ed25519.py b/ecosystem/python/sdk/aptos_sdk/ed25519.py index c8fa3dd346439..2d3bc0e552cda 100644 --- a/ecosystem/python/sdk/aptos_sdk/ed25519.py +++ b/ecosystem/python/sdk/aptos_sdk/ed25519.py @@ -3,7 +3,6 @@ from __future__ import annotations -import hashlib import unittest from typing import List, Tuple @@ -94,7 +93,7 @@ def serialize(self, serializer: Serializer): serializer.to_bytes(self.key.encode()) -class MultiEd25519PublicKey: +class MultiPublicKey: keys: List[PublicKey] threshold: int @@ -116,11 +115,6 @@ def __init__(self, keys: List[PublicKey], threshold: int, checked=True): def __str__(self) -> str: return f"{self.threshold}-of-{len(self.keys)} Multi-Ed25519 public key" - def auth_key(self) -> bytes: - hasher = hashlib.sha3_256() - hasher.update(self.to_bytes() + b"\x01") - return hasher.digest() - def to_bytes(self) -> bytes: concatenated_keys = bytes() for key in self.keys: @@ -128,11 +122,11 @@ def to_bytes(self) -> bytes: return concatenated_keys + bytes([self.threshold]) @staticmethod - def from_bytes(key: bytes) -> MultiEd25519PublicKey: + def from_bytes(key: bytes) -> MultiPublicKey: # Get key count and threshold limits. - min_keys = MultiEd25519PublicKey.MIN_KEYS - max_keys = MultiEd25519PublicKey.MAX_KEYS - min_threshold = MultiEd25519PublicKey.MIN_THRESHOLD + min_keys = MultiPublicKey.MIN_KEYS + max_keys = MultiPublicKey.MAX_KEYS + min_threshold = MultiPublicKey.MIN_THRESHOLD # Get number of signers. n_signers = int(len(key) / PublicKey.LENGTH) assert ( @@ -149,7 +143,7 @@ def from_bytes(key: bytes) -> MultiEd25519PublicKey: start_byte = i * PublicKey.LENGTH end_byte = (i + 1) * PublicKey.LENGTH keys.append(PublicKey(VerifyKey(key[start_byte:end_byte]))) - return MultiEd25519PublicKey(keys, threshold) + return MultiPublicKey(keys, threshold) def serialize(self, serializer: Serializer): serializer.to_bytes(self.to_bytes()) @@ -186,13 +180,13 @@ def serialize(self, serializer: Serializer): serializer.to_bytes(self.signature) -class MultiEd25519Signature: +class MultiSignature: signatures: List[Signature] bitmap: bytes def __init__( self, - public_key: MultiEd25519PublicKey, + public_key: MultiPublicKey, signatures_map: List[Tuple[PublicKey, Signature]], ): self.signatures = list() @@ -261,16 +255,9 @@ def test_multisig(self): "1e70e49b78f976644e2c51754a2f049d3ff041869c669523ba95b172c7329901" ) # Generate multisig public key with threshold of 1. - multisig_public_key = MultiEd25519PublicKey( + multisig_public_key = MultiPublicKey( [private_key_1.public_key(), private_key_2.public_key()], 1 ) - # Check expected authentication key. - expected_authentication_key = ( - "835bb8c5ee481062946b18bbb3b42a40b998d6bf5316ca63834c959dc739acf0" - ) - self.assertEqual( - multisig_public_key.auth_key().hex(), expected_authentication_key - ) # Get public key BCS representation. serializer = Serializer() multisig_public_key.serialize(serializer) @@ -284,7 +271,7 @@ def test_multisig(self): # Get public key bytes representation. public_key_bytes = multisig_public_key.to_bytes() # Convert back to multisig class instance from bytes. - multisig_public_key = MultiEd25519PublicKey.from_bytes(public_key_bytes) + multisig_public_key = MultiPublicKey.from_bytes(public_key_bytes) # Get public key BCS representation. serializer = Serializer() multisig_public_key.serialize(serializer) @@ -294,7 +281,7 @@ def test_multisig(self): # Have one signer sign arbitrary message. signature = private_key_2.sign(b"multisig") # Compose multisig signature. - multisig_signature = MultiEd25519Signature( + multisig_signature = MultiSignature( multisig_public_key, [(private_key_2.public_key(), signature)] ) # Get signature BCS representation. @@ -312,46 +299,43 @@ def test_multisig(self): def test_multisig_range_checks(self): # Generate public keys. keys = [ - PrivateKey.random().public_key() - for x in range(MultiEd25519PublicKey.MAX_KEYS + 1) + PrivateKey.random().public_key() for x in range(MultiPublicKey.MAX_KEYS + 1) ] # Verify failure for initializing multisig instance with too few keys. with self.assertRaisesRegex(AssertionError, "Must have between 2 and 32 keys."): - MultiEd25519PublicKey([keys[0]], 1) + MultiPublicKey([keys[0]], 1) # Verify failure for initializing multisig instance with too many keys. with self.assertRaisesRegex(AssertionError, "Must have between 2 and 32 keys."): - MultiEd25519PublicKey(keys, 1) + MultiPublicKey(keys, 1) # Verify failure for initializing multisig instance with small threshold. with self.assertRaisesRegex( AssertionError, "Threshold must be between 1 and 4." ): - MultiEd25519PublicKey(keys[0:4], 0) + MultiPublicKey(keys[0:4], 0) # Verify failure for initializing multisig instance with large threshold. with self.assertRaisesRegex( AssertionError, "Threshold must be between 1 and 4." ): - MultiEd25519PublicKey(keys[0:4], 5) + MultiPublicKey(keys[0:4], 5) # Verify failure for initializing from bytes with too few keys. with self.assertRaisesRegex(AssertionError, "Must have between 2 and 32 keys."): - MultiEd25519PublicKey.from_bytes( - MultiEd25519PublicKey([keys[0]], 1, checked=False).to_bytes() + MultiPublicKey.from_bytes( + MultiPublicKey([keys[0]], 1, checked=False).to_bytes() ) # Verify failure for initializing from bytes with too many keys. with self.assertRaisesRegex(AssertionError, "Must have between 2 and 32 keys."): - MultiEd25519PublicKey.from_bytes( - MultiEd25519PublicKey(keys, 1, checked=False).to_bytes() - ) + MultiPublicKey.from_bytes(MultiPublicKey(keys, 1, checked=False).to_bytes()) # Verify failure for initializing from bytes with small threshold. with self.assertRaisesRegex( AssertionError, "Threshold must be between 1 and 4." ): - MultiEd25519PublicKey.from_bytes( - MultiEd25519PublicKey(keys[0:4], 0, checked=False).to_bytes() + MultiPublicKey.from_bytes( + MultiPublicKey(keys[0:4], 0, checked=False).to_bytes() ) # Verify failure for initializing from bytes with large threshold. with self.assertRaisesRegex( AssertionError, "Threshold must be between 1 and 4." ): - MultiEd25519PublicKey.from_bytes( - MultiEd25519PublicKey(keys[0:4], 5, checked=False).to_bytes() + MultiPublicKey.from_bytes( + MultiPublicKey(keys[0:4], 5, checked=False).to_bytes() ) diff --git a/ecosystem/python/sdk/examples/async-aptos-token.py b/ecosystem/python/sdk/examples/async-aptos-token.py new file mode 100644 index 0000000000000..78cb3bf532f5a --- /dev/null +++ b/ecosystem/python/sdk/examples/async-aptos-token.py @@ -0,0 +1,116 @@ +# Copyright © Aptos Foundation +# SPDX-License-Identifier: Apache-2.0 + +import asyncio + +from aptos_sdk.account import Account +from aptos_sdk.account_address import AccountAddress +from aptos_sdk.aptos_token_client import (AptosTokenClient, Property, + PropertyMap) +from aptos_sdk.async_client import FaucetClient, RestClient + +from .common import FAUCET_URL, NODE_URL + + +async def main(): + rest_client = RestClient(NODE_URL) + faucet_client = FaucetClient(FAUCET_URL, rest_client) + token_client = AptosTokenClient(rest_client) + alice = Account.generate() + bob = Account.generate() + + collection_name = "Alice's" + token_name = "Alice's first token" + + print("\n=== Addresses ===") + print(f"Alice: {alice.address()}") + print(f"Bob: {bob.address()}") + + bob_fund = faucet_client.fund_account(alice.address(), 100_000_000) + alice_fund = faucet_client.fund_account(bob.address(), 100_000_000) + await asyncio.gather(*[bob_fund, alice_fund]) + + print("\n=== Initial Coin Balances ===") + alice_balance = rest_client.account_balance(alice.address()) + bob_balance = rest_client.account_balance(bob.address()) + [alice_balance, bob_balance] = await asyncio.gather(*[alice_balance, bob_balance]) + print(f"Alice: {alice_balance}") + print(f"Bob: {bob_balance}") + + print("\n=== Creating Collection and Token ===") + + txn_hash = await token_client.create_collection( + alice, + "Alice's simple collection", + 1, + collection_name, + "https://aptos.dev", + True, + True, + True, + True, + True, + True, + True, + True, + True, + 0, + 1, + ) + await rest_client.wait_for_transaction(txn_hash) + + txn_hash = await token_client.mint_token( + alice, + collection_name, + "Alice's simple token", + token_name, + "https://aptos.dev/img/nyan.jpeg", + PropertyMap([Property.string("string", "string value")]), + ) + await rest_client.wait_for_transaction(txn_hash) + + collection_addr = AccountAddress.for_named_collection( + alice.address(), collection_name + ) + token_addr = AccountAddress.for_named_token( + alice.address(), collection_name, token_name + ) + """ + alice_address = AccountAddress.from_hex("0xa018017dc40fd081d2001acdb2660058ed2011f2790a42c2a40bab99909fbde5") + collection_addr = AccountAddress.for_named_collection(alice_address, collection_name) + token_addr = AccountAddress.for_named_token(alice_address, collection_name, token_name) + """ + + collection_data = await token_client.read_object(collection_addr) + print(f"Alice's collection: {collection_data}") + token_data = await token_client.read_object(token_addr) + print(f"Alice's token: {token_data}") + + txn_hash = await token_client.add_token_property( + alice, token_addr, Property.bool("test", False) + ) + await rest_client.wait_for_transaction(txn_hash) + token_data = await token_client.read_object(token_addr) + print(f"Alice's token: {token_data}") + txn_hash = await token_client.remove_token_property(alice, token_addr, "string") + await rest_client.wait_for_transaction(txn_hash) + token_data = await token_client.read_object(token_addr) + print(f"Alice's token: {token_data}") + txn_hash = await token_client.update_token_property( + alice, token_addr, Property.bool("test", True) + ) + await rest_client.wait_for_transaction(txn_hash) + token_data = await token_client.read_object(token_addr) + print(f"Alice's token: {token_data}") + txn_hash = await token_client.add_token_property( + alice, token_addr, Property.bytes("bytes", b"\x00\x01") + ) + await rest_client.wait_for_transaction(txn_hash) + token_data = await token_client.read_object(token_addr) + print(f"Alice's token: {token_data}") + + await rest_client.close() + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/ecosystem/python/sdk/examples/multisig.py b/ecosystem/python/sdk/examples/multisig.py index 953fcf3acc6a0..e5d4b78032b74 100644 --- a/ecosystem/python/sdk/examples/multisig.py +++ b/ecosystem/python/sdk/examples/multisig.py @@ -6,7 +6,7 @@ from aptos_sdk.authenticator import Authenticator, MultiEd25519Authenticator from aptos_sdk.bcs import Serializer from aptos_sdk.client import FaucetClient, RestClient -from aptos_sdk.ed25519 import MultiEd25519PublicKey, MultiEd25519Signature +from aptos_sdk.ed25519 import MultiPublicKey, MultiSignature from aptos_sdk.transactions import (EntryFunction, RawTransaction, Script, ScriptArgument, SignedTransaction, TransactionArgument, TransactionPayload) @@ -49,7 +49,7 @@ def wait(): # :!:>section_2 threshold = 2 - multisig_public_key = MultiEd25519PublicKey( + multisig_public_key = MultiPublicKey( [alice.public_key(), bob.public_key(), chad.public_key()], threshold ) @@ -129,7 +129,7 @@ def wait(): (bob.public_key(), bob_signature), ] - multisig_signature = MultiEd25519Signature(multisig_public_key, sig_map) + multisig_signature = MultiSignature(multisig_public_key, sig_map) authenticator = Authenticator( MultiEd25519Authenticator(multisig_public_key, multisig_signature) @@ -197,7 +197,7 @@ def wait(): cap_rotate_key = deedee.sign(rotation_proof_challenge_bcs).data() - cap_update_table = MultiEd25519Signature( + cap_update_table = MultiSignature( multisig_public_key, [ (bob.public_key(), bob.sign(rotation_proof_challenge_bcs)), @@ -309,7 +309,7 @@ def wait(): (chad.public_key(), chad_signature), ] - multisig_signature = MultiEd25519Signature(multisig_public_key, sig_map) + multisig_signature = MultiSignature(multisig_public_key, sig_map) authenticator = Authenticator( MultiEd25519Authenticator(multisig_public_key, multisig_signature) @@ -392,7 +392,7 @@ def wait(): (chad.public_key(), chad_signature), ] - multisig_signature = MultiEd25519Signature(multisig_public_key, sig_map) + multisig_signature = MultiSignature(multisig_public_key, sig_map) authenticator = Authenticator( MultiEd25519Authenticator(multisig_public_key, multisig_signature) @@ -449,7 +449,7 @@ def wait(): (bob.public_key(), bob_signature), ] - multisig_signature = MultiEd25519Signature(multisig_public_key, sig_map) + multisig_signature = MultiSignature(multisig_public_key, sig_map) authenticator = Authenticator( MultiEd25519Authenticator(multisig_public_key, multisig_signature) diff --git a/third_party/move/move-prover/move-abigen/src/abigen.rs b/third_party/move/move-prover/move-abigen/src/abigen.rs index eca389e87fa0f..d36d41a16c9ed 100644 --- a/third_party/move/move-prover/move-abigen/src/abigen.rs +++ b/third_party/move/move-prover/move-abigen/src/abigen.rs @@ -286,25 +286,27 @@ impl<'env> Abigen<'env> { TypeTag::Vector(Box::new(tag)) }, Struct(module_id, struct_id, vec_type) => { - let expect_msg = format!("type {:?} is not allowed in scription function", ty0); let struct_module_env = module_env.env.get_module(*module_id); let abilities = struct_module_env.get_struct(*struct_id).get_abilities(); if abilities.has_ability(Ability::Copy) && !abilities.has_ability(Ability::Key) { + let mut type_params = vec![]; + for e in vec_type { + let type_param = match Self::get_type_tag(e, module_env)? { + Some(type_param) => type_param, + None => return Ok(None), + }; + type_params.push(type_param); + } TypeTag::Struct(Box::new(StructTag { address: *struct_module_env.self_address(), module: struct_module_env.get_identifier(), name: struct_module_env .get_struct(*struct_id) .get_identifier() - .unwrap_or_else(|| panic!("{}", expect_msg)), - type_params: vec_type - .iter() - .map(|e| { - Self::get_type_tag(e, module_env) - .unwrap_or_else(|_| panic!("{}", expect_msg)) - }) - .map(|e| e.unwrap_or_else(|| panic!("{}", expect_msg))) - .collect(), + .unwrap_or_else(|| { + panic!("type {:?} is not allowed in entry function", ty0) + }), + type_params, })) } else { return Ok(None); diff --git a/types/src/account_address.rs b/types/src/account_address.rs index 3ff3b6004e8f5..599708507db75 100644 --- a/types/src/account_address.rs +++ b/types/src/account_address.rs @@ -284,6 +284,13 @@ mod test { "{:?}", super::create_token_address(address, "bob's collection", "bob's token") ); - // println!("{:?}", create_object_address(address, guid); + println!( + "{:?}", + super::create_collection_address(address, "bob's collection") + ); + println!( + "{:?}", + super::create_resource_address(address, &[0x0B, 0x00, 0x0B]) + ); } }