## IPFS介紹 #### 我們這次要使用IPFS(Pinata)來存放我們的NFT圖片。 有關IPFS以及Pinata介紹,請看這篇文章 [IPFS介紹](https://hackmd.io/7vj9f0HiQXGfo_j1_u0KfA?view) ## 上傳圖片至Pinata 我們使用Pinata當作我們儲存圖片的IPFS系統。 [Pinata上傳圖片頁面](https://app.pinata.cloud/pinmanager) ![](https://hackmd.io/_uploads/rkvIzlxyp.png) 首先我們點選右上角的 "Add Files" 按鈕,然後點選 "File",會有上傳視窗讓你選擇圖片。 ![](https://hackmd.io/_uploads/ByjgQlxJT.png) 這邊可以隨意上傳隨便一張圖片,GIF檔也可以。 ![](https://turquoise-smiling-halibut-906.mypinata.cloud/ipfs/QmUnLrNWquR3H4HZtLHLmhBy4zKebMdmqRTZaqJLrTraM4) 上傳好後,我們可以看到有出現我們剛剛上傳的檔案以及對應的CID,這個CID就是你圖片的類似代號的東西,我們待會在Mint NFT的時候會用到。 ![](https://hackmd.io/_uploads/SJaLHlx1T.png) ## Publisher + Display 這次主要會使用到Publisher以及Display兩個Sui Framwork內的module。 #### Publisher 作為代表發布者權限的一種方式。 該物件本身並沒有任何特定的用法,有兩個主要驗證的功能:```package::from_module<T>```以及```package::from_package<T>``` 檢查類型T是否屬於為其Publisher創建物件的package或module。 要設置Publisher,需要一次性見證(OTW) - 通過這種方式,我們確保Publisher僅初始化一次。 #### Object Display 擁有Publisher對象的創建者或構建者可以使用```sui::display```來定義其物件的顯示屬性。 Sui Object Display 是一個模板顯示標準,允許在鏈上顯示配置。它能夠把鏈下數據替換到模板中。 可以設置哪些字段沒有限制,所有對象屬性都可以通過語法訪問{property}並作為模板字符串的一部分插入。 目前定義的模板內容如下: ```javascript { "name": "{name}", //顯示名稱 "link": "https://sui-heroes.io/hero/{id}", //可以放入連結到自己的商品網址 "image_url": "ipfs://{img_url}", //使用ipfs(推薦)或是一般Https圖片網址 "description": "A true Hero of the Sui ecosystem!", //敘述 "project_url": "https://sui-heroes.io", //放入連結到自己的網站 "creator": "Unknown Sui Fan" //創建人名稱 } ``` ## NFT智能合約 ```rust module nft_demo::my_hero { use sui::tx_context::{Self, TxContext}; use std::string::{Self, String}; use sui::transfer; use sui::object::{Self, UID}; use sui::package; use sui::display; struct Hero has key, store { id: UID, name: String, img_url: String, description: String, creator: String } /// One-Time-Witness for the module. struct MY_HERO has drop {} fun init(otw: MY_HERO, ctx: &mut TxContext) { let keys = vector[ string::utf8(b"name"), string::utf8(b"link"), string::utf8(b"image_url"), string::utf8(b"description"), string::utf8(b"project_url"), string::utf8(b"creator"), ]; let values = vector[ // For `name` we can use the `Hero.name` property string::utf8(b"{name}"), // For `link` we can build a URL using an `id` property string::utf8(b"https://sui-heroes.io/hero/{id}"), // For `image_url` we use an ipfs :// + `img_url` or https:// + `img_url`. string::utf8(b"{img_url}"), // Description is static for all `Hero` objects. string::utf8(b"{description}"), // Project URL is usually static string::utf8(b"https://sui-heroes.io"), // Creator field can be any string::utf8(b"{creator}") ]; // Claim the `Publisher` for the package! let publisher = package::claim(otw, ctx); // Get a new `Display` object for the `Hero` type. let display = display::new_with_fields<Hero>( &publisher, keys, values, ctx ); // Commit first version of `Display` to apply changes. display::update_version(&mut display); transfer::public_transfer(publisher, tx_context::sender(ctx)); transfer::public_transfer(display, tx_context::sender(ctx)); } /// Anyone can mint their `Hero`! public entry fun mint( name: String, img_url: String, description: String, creator: String, ctx: &mut TxContext ) { let id = object::new(ctx); let hero = Hero { id, name, img_url, description, creator }; transfer::public_transfer(hero, tx_context::sender(ctx)); } /// Permanently delete `nft` public entry fun burn(nft: Hero) { let Hero { id, name: _ , img_url: _ , description: _ , creator:_ } = nft; object::delete(id); } } ``` ### 部署智能合約 把智能合約部署上鏈後,我們可以使用 [Sui Explorer](https://suiexplorer.com/?network=testnet) 來使用我們剛剛開發的mint功能,來mint一個NFT給自己 ### Mint NFT 先來查看要傳入哪些參數 ![](https://hackmd.io/_uploads/B1qr1Hg16.png) 第一個參數傳入NFT名稱 第二個參數傳入ipfs://{CID} ![](https://hackmd.io/_uploads/Sy7A1BlJa.png) 第三個參數傳入NFT敘述 第四個參數傳入建造者名稱 ![](https://hackmd.io/_uploads/ryuhyBg16.png) ![](https://hackmd.io/_uploads/B1W7eSgkT.png) 在我們的錢包內,點選Assets,也可看到我們剛剛mint出來的NFT ![](https://hackmd.io/_uploads/B1eOgHxJ6.png) ### Burn NFT 傳入需要銷毀的NFT Object ID ![](https://hackmd.io/_uploads/HyC0lBxka.png) 會發現Sui Explorer以及錢包都找不到該NFT了 ![](https://hackmd.io/_uploads/HJOMWrgkp.png) ![](https://hackmd.io/_uploads/H1NQ-rx1p.png)