Move language can easily implement NFT protocol

Starcoin
3 min readOct 15, 2021

--

1. NFT Protocol V1

In the below code segment, we implement two functionalities: initialize and mint NFT.

  • Line 6: Define NFT struct
  • Line 8: Define UniqIdList struct to store NFT
  • Line 12: Initialize UniqIdList to receive and store NFT
  • Line 16: First, this function will use assert to make a decision to receive this NFT or not, if the NFT can not be received, exit and return error code, to guarantee that NFT can not be received by the account which is illegal.
1    address 0x2 {
2 module NFTExample1 {
3 use 0x1::Signer;
4 use 0x1::Vector;
5
6 struct NFT has key, store { name: vector<u8> }
7
8 struct UniqIdList has key, store {
9 data: vector<vector<u8>>
10 }
11
12 public fun initialize(account: &signer) {
13 move_to(account, UniqIdList {data: Vector::empty<vector<u8>>()});
14 }
15
16 public fun new(account: &signer, name: vector<u8>): NFT acquires UniqIdList {
17 let account_address = Signer::address_of(account);
18 let exist = Vector::contains<vector<u8>>(&borrow_global<UniqIdList>(account_address).data, &name);
19 assert(!exist, 1);
20 let id_list = borrow_global_mut<UniqIdList>(account_address);
21 Vector::push_back<vector<u8>>(&mut id_list.data, copy name);
22 NFT { name }
23 }
24 }
25 }

2. NFT Protocol V2

Use struct to construct NFT, but you will need to rewrite the code if you need another type of NFT, generics can solve this issue.

  • Line 6: Define generic NFT struct
  • Line 8: Define generic UniqIdList struct
  • Line 12: Initialize UniqIdList with vector
  • Line 16: Generic struct and function will be returned and called

Now this code segment is not completed, but it can be used to test multiple NFT with some scope.

1    address 0x2 {
2 module NFTExample2 {
3 use 0x1::Signer;
4 use 0x1::Vector;
5
6 struct NFT<T: store> has key, store { name: T }
7
8 struct UniqIdList<T: store> has key, store {
9 data: vector<T>
10 }
11
12 public fun initialize(account: &signer) {
13 move_to(account, UniqIdList {data: Vector::empty<vector<u8>>()});
14 }
15
16 public fun new(account: &signer, name: vector<u8>): NFT<vector<u8>> acquires UniqIdList {
17 let account_address = Signer::address_of(account);
18 let exist = Vector::contains<vector<u8>>(&borrow_global<UniqIdList<vector<u8>>> (account_address).data, &name);
19 assert(!exist, 1);
20 let id_list = borrow_global_mut<UniqIdList<vector<u8>>>(account_address);
21 Vector::push_back<vector<u8>>(&mut id_list.data, copy name);
22 NFT { name }
23 }
24 }
25 }

3. NFT Protocol V3

In the above code segment, we used generic parameters in the new and initialize functions. We need to modify these two functions if we prefer to make this frame complete.

Use generic to decorate new and initialize to make these two functions could be applied to more multiple NFT tests.

1    address 0x2 {
2 module NFTExample3 {
3 use 0x1::Signer;
4 use 0x1::Vector;
5
6 struct NFT<T: store> has key, store { name: T }
7
8 struct UniqIdList<T: store> has key, store {
9 data: vector<T>
10 }
11
12 public fun initialize<T: store>(account: &signer) {
13 move_to(account, UniqIdList {data: Vector::empty<T>()});
14 }
15
16 public fun new<T: store + copy>(account: &signer, name: T): NFT<T> acquires UniqIdList {
17 let account_address = Signer::address_of(account);
18 let exist = Vector::contains<T>(&borrow_global<UniqIdList<T>>(account_address).data, &name);
19 assert(!exist, 1);
20 let id_list = borrow_global_mut<UniqIdList<T>>(account_address);
21 Vector::push_back<T>(&mut id_list.data, copy name);
22 NFT { name }
23 }
24 }
25 }

4. NFT Protocol V4

We can add events to this NFT protocol, so that we can add notify functionality. This code segment is relatively completed, but you still can add other functionalities,such as, transfer, destroy, work with frontend, and make beautiful NFT.

1    address 0x2 {
2 module NFTExample4 {
3 use 0x1::Vector;
4 use 0x1::Event;
5
6 struct NFT<T: store> has key, store { name: T }
7
8 struct UniqIdList<T: store + drop> has key, store {
9 data: vector<T>,
10 nft_events: Event::EventHandle<NFTEvent<T>>,
11 }
12
13 struct NFTEvent<T: store + drop> has drop, store {
14 name: T,
15 }
16
17 public fun initialize<T: store + drop>(account: &signer) {
18 move_to(account, UniqIdList {data: Vector::empty<T>(), nft_events: Event::new_event_handle<NFTEvent<T>>(account)});
19 }
20
21 public fun new<T: store + copy + drop>(_account: &signer, account_address:address, name: T): NFT<T> acquires UniqIdList {
22 let exist = Vector::contains<T>(&borrow_global<UniqIdList<T>>(account_address).data, &name);
23 assert(!exist, 1);
24 let id_list = borrow_global_mut<UniqIdList<T>>(account_address);
25 Vector::push_back<T>(&mut id_list.data, copy name);
26 let new_name = copy name;
27 Event::emit_event(&mut id_list.nft_events, NFTEvent { name:new_name });
28 NFT { name }
29 }
30 }
31 }

--

--

Starcoin
Starcoin

Written by Starcoin

Starcoin is a proof-of-work blockchain that enables secure smart contracts based on Move to power services in Web 3.0

No responses yet