1
+ module nft ::nftlist {
2
+ use std::option;
3
+ use std::signer;
4
+ use std::string;
5
+ use aptos_std::string_utils;
6
+ use aptos_framework::account;
7
+ use aptos_framework::account::SignerCapability ;
8
+ use aptos_framework::event;
9
+ use aptos_framework::object;
10
+ use aptos_framework::object::Object ;
11
+
12
+ use aptos_token_objects::collection;
13
+ use aptos_token_objects::royalty;
14
+ use aptos_token_objects::token;
15
+ use aptos_token_objects::token::Token ;
16
+
17
+ // ERROR CODE
18
+ const ERROR_NOWNER : u64 = 1 ;
19
+ const ResourceAccountSeed: vector <u8 > = b"mfers ";
20
+ const CollectionDescription: vector <u8 > = b"mfers are generated entirely from hand drawings by sartoshi. this project is in the public domain; feel free to use mfers any way you want. ";
21
+ const CollectionName: vector <u8 > = b"mfers ";
22
+ const CollectionURI: vector <u8 > = b"ipfs://QmWmgfYhDWjzVheQyV2TnpVXYnKR25oLWCB2i9JeBxsJbz ";
23
+ const TokenURI: vector <u8 > = b"ipfs://bafybeiearr64ic2e7z5ypgdpu2waasqdrslhzjjm65hrsui2scqanau3ya/ ";
24
+ const TokenPrefix: vector <u8 > = b"mfer # ";
25
+
26
+ struct ResourceCap has key {
27
+ cap: SignerCapability
28
+ }
29
+
30
+ struct CollectionRefsStore has key {
31
+ mutator_ref: collection::MutatorRef
32
+ }
33
+
34
+ struct TokenRefsStore has key {
35
+ mutator_ref: token::MutatorRef ,
36
+ burn_ref: token::BurnRef ,
37
+ extend_ref: object::ExtendRef ,
38
+ transfer_ref: option::Option <object::TransferRef >
39
+ }
40
+
41
+ struct Content has key {
42
+ content: string::String
43
+ }
44
+
45
+ #[event]
46
+ struct MintEvent has key , drop , store {
47
+ owner: address ,
48
+ token_id: address ,
49
+ content: string::String
50
+ }
51
+
52
+ #[event]
53
+ struct SetContentEvent has drop , store {
54
+ owner: address ,
55
+ token_id: address ,
56
+ old_content: string::String ,
57
+ new_content: string::String
58
+ }
59
+
60
+ #[event]
61
+ struct BurnEvent has drop , store {
62
+ owner: address ,
63
+ token_id: address ,
64
+ content: string::String
65
+ }
66
+
67
+
68
+ fun init_module (sender: &signer ) {
69
+ let (resource_signer, resource_cap) = account::create_resource_account (
70
+ sender,
71
+ ResourceAccountSeed
72
+ );
73
+
74
+ move_to (
75
+ &resource_signer,
76
+ ResourceCap {
77
+ cap: resource_cap
78
+ }
79
+ );
80
+
81
+ let max_supply = 20 ;
82
+ let collection_cref = collection::create_fixed_collection (
83
+ &resource_signer,
84
+ string::utf8 (CollectionDescription ),
85
+ max_supply,
86
+ string::utf8 (CollectionName ),
87
+ option::some (royalty::create (5 , 100 , signer ::address_of (sender))),
88
+ string::utf8 (CollectionURI )
89
+ );
90
+
91
+ let collection_signer = object::generate_signer (&collection_cref);
92
+
93
+ let mutator_ref = collection::generate_mutator_ref (&collection_cref);
94
+
95
+ move_to (
96
+ &collection_signer,
97
+ CollectionRefsStore {
98
+ mutator_ref
99
+ }
100
+ );
101
+ }
102
+
103
+ entry public fun mint (
104
+ sender: &signer ,
105
+ content: string::String
106
+ ) acquires ResourceCap {
107
+ let resource_cap = &borrow_global <ResourceCap >(
108
+ account::create_resource_address (
109
+ &@nft ,
110
+ ResourceAccountSeed
111
+ )
112
+ ).cap;
113
+
114
+ let resource_signer = &account::create_signer_with_capability (
115
+ resource_cap
116
+ );
117
+ let url = string::utf8 (TokenURI );
118
+
119
+ let token_cref = token::create_numbered_token (
120
+ resource_signer,
121
+ string::utf8 (CollectionName ),
122
+ string::utf8 (CollectionDescription ),
123
+ string::utf8 (TokenPrefix ),
124
+ string::utf8 (b""),
125
+ option::none (),
126
+ string::utf8 (b""),
127
+ );
128
+
129
+ let id = token::index <Token >(object::object_from_constructor_ref (&token_cref));
130
+ string::append (&mut url, string_utils::to_string (&id));
131
+ string::append (&mut url, string::utf8 (b".png "));
132
+
133
+ let token_signer = object::generate_signer (&token_cref);
134
+
135
+ // create token_mutator_ref
136
+ let token_mutator_ref = token::generate_mutator_ref (&token_cref);
137
+
138
+ token::set_uri (&token_mutator_ref, url);
139
+
140
+ // create generate_burn_ref
141
+ let token_burn_ref = token::generate_burn_ref (&token_cref);
142
+
143
+ // if you want stop transfer ( must save transfer_ref
144
+ // let transfer_ref = object::generate_transfer_ref(&token_cref);
145
+ // object::disable_ungated_transfer(&transfer_ref);
146
+
147
+ move_to (
148
+ &token_signer,
149
+ TokenRefsStore {
150
+ mutator_ref: token_mutator_ref,
151
+ burn_ref: token_burn_ref,
152
+ extend_ref: object::generate_extend_ref (&token_cref),
153
+ transfer_ref: option::none ()
154
+ }
155
+ );
156
+
157
+ move_to (
158
+ &token_signer,
159
+ Content {
160
+ content
161
+ }
162
+ );
163
+
164
+
165
+
166
+ event::emit (
167
+ MintEvent {
168
+ owner: signer ::address_of (sender),
169
+ token_id: object::address_from_constructor_ref (&token_cref),
170
+ content
171
+ }
172
+ );
173
+
174
+
175
+
176
+ object::transfer (
177
+ resource_signer,
178
+ object::object_from_constructor_ref <Token >(&token_cref),
179
+ signer ::address_of (sender),
180
+ )
181
+
182
+
183
+ }
184
+
185
+
186
+ entry fun burn (
187
+ sender: &signer ,
188
+ object: Object <Content >
189
+ ) acquires TokenRefsStore , Content {
190
+ assert !(object::is_owner (object, signer ::address_of (sender)), ERROR_NOWNER );
191
+ let TokenRefsStore {
192
+ mutator_ref: _,
193
+ burn_ref,
194
+ extend_ref: _,
195
+ transfer_ref: _
196
+ } = move_from <TokenRefsStore >(object::object_address (&object));
197
+
198
+ let Content {
199
+ content
200
+ } = move_from <Content >(object::object_address (&object));
201
+
202
+ event::emit (
203
+ BurnEvent {
204
+ owner: object::owner (object),
205
+ token_id: object::object_address (&object),
206
+ content
207
+ }
208
+ );
209
+
210
+ token::burn (burn_ref);
211
+ }
212
+
213
+ entry fun set_content (
214
+ sender: &signer ,
215
+ object: Object <Content >,
216
+ content: string::String
217
+ ) acquires Content {
218
+ let old_content = borrow_content (signer ::address_of (sender), object).content;
219
+ event::emit (
220
+ SetContentEvent {
221
+ owner: object::owner (object),
222
+ token_id: object::object_address (&object),
223
+ old_content,
224
+ new_content: content
225
+ }
226
+ );
227
+ borrow_mut_content (signer ::address_of (sender), object).content = content;
228
+ }
229
+
230
+ #[view]
231
+ public fun get_content (object: Object <Content >): string::String acquires Content {
232
+ borrow_global <Content >(object::object_address (&object)).content
233
+ }
234
+
235
+ inline fun borrow_content (owner: address , object: Object <Content >): &Content {
236
+ assert !(object::is_owner (object, owner), ERROR_NOWNER );
237
+ borrow_global <Content >(object::object_address (&object))
238
+ }
239
+
240
+ inline fun borrow_mut_content (owner: address , object: Object <Content >): &mut Content {
241
+ assert !(object::is_owner (object, owner), ERROR_NOWNER );
242
+ borrow_global_mut <Content >(object::object_address (&object))
243
+ }
244
+
245
+ #[test_only]
246
+ public fun init_for_test (sender: &signer ) {
247
+ init_module (sender)
248
+ }
249
+ }
0 commit comments