入门 Sui Move 开发:5. 发布同质化代币 — NFT

  • greyhao
  • 更新于 2024-11-16 09:40
  • 阅读 335

如何在 Sui 链上发布一个 NFT

如果你是初学者,强烈建议看下前几节内容:

入门 Sui Move 开发:1. 环境安装 

 入门 Sui Move 开发:2. 常用命令、编写并发布 Hello World 合约

入门 Sui Move 开发:3. Sui Move 语法和设计模式 

入门 Sui Move 开发:4. Sui Move 中集合、对象、泛型、动态字段

Sui 链上发布一个非同质化代码也就是 NFT 很简单,因为在 Sui 上一切都是对象,每个对象都是独一无二的。

所以在 Sui 上实现 NFT 其实就是给对象添加所需要的字段。

一个简单的 NFT 合约

/// 发布一个 NFT 的简单合约
module nft_greyhao::nft_greyhao;

use std::string::{String , utf8};
use sui::url::{Self, Url};
use sui::event;

// NFT 对象,包含所需要的 name、description、url 信息
public struct GreyhaoNFT has key, store {
  id: UID,
  name: String,
  description: String,
  url: Url,
}

//  ====Evens ====
public struct NFTMinted has copy, drop {
  object_id: ID,
  creator: address,
  name: String,
}

fun init(ctx: &mut TxContext) {

  let url = url::new_unsafe_from_bytes(b"https://avatars.githubusercontent.com/u/107107440");

    // 创建一个 NFT 对象实例
    let nft = GreyhaoNFT {
    id: object::new(ctx),
    name: utf8(b"GREYHAO"),
    description: utf8(b"NFT was created by GreyHao."),
    url: url,
  }

  event::emit(NFTMinted {
    object_id: object::id(&nft),
    creator: recipient,
    name: nft.name,
  });

  // 将 NFT 发送给当前交易地址
  transfer::transfer(nft, tx_context::sender(ctx));
}

// mint NFT 
#[allow(lint(self_transfer))]
public fun mint(ctx: &mut TxContext){
  let recipient = tx_context::sender(ctx);

  let url = url::new_unsafe_from_bytes(b"https://avatars.githubusercontent.com/u/107107440");

  // 创建一个 NFT 对象实例
  let nft = GreyhaoNFT {
    id: object::new(ctx),
    name: utf8(b"GREYHAO"),
    description: utf8(b"NFT was created by GreyHao."),
    url: url,
  }

  event::emit(NFTMinted {
    object_id: object::id(&nft),
    creator: recipient,
    name: nft.name,
  });

  transfer::public_transfer(nft, recipient);
}

/// 转移指定 NFT 给指定地址
public fun transfer(nft: GreyhaoNFT, recipient: address, _: &mut TxContext) {
  transfer::public_transfer(nft, recipient)
}

/// mint NFT 并发送给指定地址
public fun mint_and_transfer(recipient: address, ctx: &mut TxContext) {
  let nft = GreyhaoNFT {
    id: object::new(ctx),
    name: utf8(b"GREYHAO"),
    description: utf8(b"NFT was created by GreyHao."),
    url: url,
  }
  transfer::public_transfer(nft, recipient)
}

/// 删除指定 NFT 对象
public fun burn(nft: GreyhaoNFT, _: &mut TxContext) {
  let GreyhaoNFT {id, name: _, description: _, url: _} = nft;
  id.delete()
}

发布合约之后,在浏览器搜索创建的类型为 合约地址::nft_greyhao::GreyhaoNFT,可以看到如下图所展示的内容。

image.png

Display 对象,实现在浏览器上自动展示 NFT 信息

上图中跟我期望的有一些不同,怎么上图中没有看到NFT图片。 接下来就要用到 Display 对象。

Display 对象可以实现链上数据更友好可读的一种模版引擎。通过开发者定义如何将特定的结构或对象格式化为用户友好的字符串表示,在前端中更清晰展示。

只需在 init 方法中添加 Display 相关模版内容,就可以实现当我们在浏览器中搜索 NFT 对象(发布合约时创建的类型为 ObjectType 的对象)所对应的 ObjectID 时就可以看到对应的图片及其他信息。

let keys = vector[
    b"name".to_string(),
    b"link".to_string(),
    b"image_url".to_string(),
    b"description".to_string(),
    b"project_url".to_string(),
    b"creator".to_string(),
  ];

  let values = vector[
    b"{name}".to_string(),
    b"https://sui-heroes.io/hero/{id}".to_string(),
    b"{image_url}".to_string(),
    b"A true Hero of the Sui ecosystem!".to_string(),
    b"https://sui-heroes.io".to_string(),
    b"Unknown NFT Fan".to_string(),
  ];

  let publisher = package::claim(otw, ctx);

  let mut display = display::new_with_fields<GreyhaoNFT>(&publisher, keys, values, ctx);

  display.update_version();

  transfer::public_transfer(publisher, ctx.sender());
  transfer::public_transfer(display, ctx.sender());

image.png

使用 display 的完整代码

/// 发布一个 NFT 的简单合约
module nft_greyhao::nft_greyhao;

use std::string::{String , utf8};
use sui::url::{Self, Url};
use sui::event;
use sui::package;
use sui::display;

// NFT 对象,包含所需要的 name、description、url 信息
public struct GreyhaoNFT has key, store {
  id: UID,
  name: String,
  description: String,
  url: Url,
}

//  ====Evens ====
public struct NFTMinted has copy, drop {
  object_id: ID,
  creator: address,
  name: String,
}

fun init(ctx: &mut TxContext) {
  // 定义 keys,keys 包含的值就是 GreyhaoNFT 对象中除 id 外的字段
  let keys = vector[
    b"name".to_string(),
    b"description".to_string(),
    b"url".to_string(),
  ];

  // 定义 key 对应的值
  let values = vector[
    b"{name}".to_string(),
    b"{description}".to_string(),
    b"{url}".to_string(),
  ];

  // 使用了 OTW, 通过 package::claim 得到一个 publisher 对象
  let publisher = package::claim(otw, ctx);

  // 使用要显示的属性创建 display 对象
  let mut display = display::new_with_fields<GreyhaoNFT>(&publisher, keys, values, ctx);

  // 更新版本
  display.update_version();

  // 将 publisher 和 display 都发送给当前交易地址
  transfer::public_transfer(publisher, ctx.sender());
  transfer::public_transfer(display, ctx.sender());

  let url = url::new_unsafe_from_bytes(b"https://avatars.githubusercontent.com/u/107107440");

    // 创建一个 NFT 对象实例
    let nft = GreyhaoNFT {
    id: object::new(ctx),
    name: utf8(b"GREYHAO"),
    description: utf8(b"NFT was created by GreyHao."),
    url: url,
  }

  event::emit(NFTMinted {
    object_id: object::id(&nft),
    creator: recipient,
    name: nft.name,
  });

  // 将 NFT 发送给当前交易地址
  transfer::transfer(nft, tx_context::sender(ctx));
}

// mint NFT 
#[allow(lint(self_transfer))]
public fun mint(ctx: &mut TxContext){
  let recipient = tx_context::sender(ctx);

  let url = url::new_unsafe_from_bytes(b"https://avatars.githubusercontent.com/u/107107440");

  // 创建一个 NFT 对象实例
  let nft = GreyhaoNFT {
    id: object::new(ctx),
    name: utf8(b"GREYHAO"),
    description: utf8(b"NFT was created by GreyHao."),
    url: url,
  }

  event::emit(NFTMinted {
    object_id: object::id(&nft),
    creator: recipient,
    name: nft.name,
  });

  transfer::public_transfer(nft, recipient);
}

/// 转移指定 NFT 给指定地址
public fun transfer(nft: GreyhaoNFT, recipient: address, _: &mut TxContext) {
  transfer::public_transfer(nft, recipient)
}

/// mint NFT 并发送给指定地址
public fun mint_and_transfer(recipient: address, ctx: &mut TxContext) {
  let nft = GreyhaoNFT {
    id: object::new(ctx),
    name: utf8(b"GREYHAO"),
    description: utf8(b"NFT was created by GreyHao."),
    url: url,
  }
  transfer::public_transfer(nft, recipient)
}

/// 删除指定 NFT 对象
public fun burn(nft: GreyhaoNFT, _: &mut TxContext) {
  let GreyhaoNFT {id, name: _, description: _, url: _} = nft;
  id.delete()
}

以上就是本节的所有内容。

如果觉得本节内容对你有所帮助,可以点赞鼓励下。

如果你对文章中内容有任何疑问可以留言。

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
greyhao
greyhao
开发过多链钱包。目前学习 Sui 合约开发中。欢迎一起学习交流