跳到主要内容

管理资产 (NFT)

本指南将全面介绍如何使用 OCAP Client 管理非同质化代币 (NFT),也称为资产的整个生命周期。您将学习如何从零开始创建新资产、更新其属性、建立用于标准化铸造的资产工厂,以及如何从该工厂获取新资产。

创建新资产

您可以使用 createAsset 方法在区块链上创建一个独立的唯一资产。每个资产都会被分配一个唯一的链上地址,该地址由其初始属性派生而来。

javascript
const { wallet } = getWallet(); // 用户的钱包对象

async function createNewAsset() {
  try {
    const [hash, address] = await client.createAsset({
      moniker: 'My Unique Digital Artwork',
      data: {
        typeUrl: 'json',
        value: {
          description: 'A one-of-a-kind piece created by Artist X.',
          imageUrl: 'https://example.com/path/to/image.png',
        },
      },
      readonly: true,
      transferrable: true,
      wallet: wallet,
    });

    console.log(`Asset creation transaction sent: ${hash}`);
    console.log(`New asset address: ${address}`);
    return address;
  } catch (error) {
    console.error('Error creating asset:', error);
  }
}

createNewAsset();

参数

  • moniker string (required) — 资产的名称。
  • parent string (default: '') — 父资产的地址(如有)。
  • data object (required) — 资产的数据负载,必须包含 typeUrl 和 value。
  • readonly boolean (default: false) — 如果为 true,资产在创建后无法更新。
  • transferrable boolean (default: true) — 如果为 true,资产可以转移到另一个账户。
  • ttl number (default: 0) — 资产首次消费后的存活时间(以秒为单位)。
  • display object — 包含资产显示信息的对象。
  • endpoint object — 包含资产端点详细信息的对象。
  • tags string[] (default: []) — 用于对资产进行分类的字符串数组。
  • wallet WalletObject (required) — 资产初始所有者的钱包对象。
  • delegator string (default: '') — 通过委托授权此交易的账户地址。

返回值

一个 Promise,它会解析为一个包含交易哈希和新资产链上地址的数组。

  • response Promise<[string, string]> — [交易哈希, 资产地址]

更新现有资产

如果资产创建时设置了 readonly: false,您可以使用 updateAsset 方法修改其 monikerdata 字段。通过资产的唯一地址来识别该资产。

javascript
const { wallet } = getWallet(); // 用户的钱包对象
const assetAddress = 'z362...'; // 要更新的资产地址

async function updateExistingAsset() {
  try {
    const hash = await client.updateAsset({
      address: assetAddress,
      moniker: 'My Updated Digital Artwork',
      data: {
        typeUrl: 'json',
        value: {
          description: 'An updated description for my unique piece.',
          imageUrl: 'https://example.com/path/to/new_image.png',
        },
      },
      wallet: wallet,
    });

    console.log(`Asset update transaction sent: ${hash}`);
  } catch (error) {
    console.error('Error updating asset:', error);
  }
}

updateExistingAsset();

参数

  • address string (required) — 要更新的资产的链上地址。
  • moniker string (required) — 资产的新名称。
  • data object (required) — 资产的更新数据负载。
  • wallet WalletObject (required) — 当前资产所有者的钱包对象。

返回值

一个 Promise,它会解析为交易哈希。

  • response Promise<string> — 交易哈希

创建资产工厂

资产工厂是用于创建多个相似资产的模板。它定义了铸造新资产的结构、规则和逻辑,比单独创建每个资产更高效。这对于发行活动门票、证书或收藏品等用例非常理想。

javascript
const { wallet } = getWallet(); // 工厂所有者的钱包

const factoryDefinition = {
  name: 'Conference Ticket Factory',
  description: 'Mints tickets for the 2024 Tech Conference.',
  limit: 1000, // 最多可铸造 1000 张门票
  input: {
    // 定义铸造资产所需的数据
    type: 'object',
    properties: {
      attendeeName: { type: 'string' },
      ticketType: { type: 'string', enum: ['General', 'VIP'] },
    },
  },
  output: {
    // 定义铸造出的资产的结构
    moniker: 'Ticket for {{attendeeName}}',
    description: '{{ticketType}} admission for the 2024 Tech Conference.',
    transferrable: false, // 门票不可转让
  },
  hooks: [],
};

async function createFactory() {
  try {
    const [hash, factoryAddress] = await client.createAssetFactory({
      factory: factoryDefinition,
      wallet: wallet,
    });

    console.log(`Factory creation transaction sent: ${hash}`);
    console.log(`New factory address: ${factoryAddress}`);
  } catch (error) {
    console.error('Error creating asset factory:', error);
  }
}

createFactory();

参数

  • factory object (required) — 一个定义工厂属性和铸造逻辑的对象。
    • name string (required) — 工厂的名称。
    • description string (required) — 工厂用途的描述。
    • limit number (default: 0) — 可以从此工厂铸造的最大资产数量。0 表示无限制。
    • trustedIssuers string[] — 被授权从此工厂铸造资产的账户地址列表。
    • input object (required) — 定义铸造资产所需的输入数据。
    • output object (required) — 定义将被铸造的资产的结构和属性。
    • hooks object[] — 在铸造过程中执行的钩子列表。
    • data object — 与工厂一起存储的额外任意数据。
  • wallet WalletObject (required) — 工厂所有者的钱包对象。

返回值

一个 Promise,它会解析为一个包含交易哈希和新工厂链上地址的数组。

  • response Promise<[string, string]> — [交易哈希, 工厂地址]

从工厂获取资产

从工厂获取资产是一个两步过程。首先,您准备铸造数据,这使您可以预览将要创建的资产。其次,您将交易提交到区块链以正式获取该资产。

这种分离很有用,因为它允许应用程序在用户签名并提交最终交易之前,向用户展示他们将要收到的东西。

步骤 1:准备资产数据

preMintAsset 方法接收工厂地址和用户提供的输入,以生成最终的资产数据。此过程在链下发生,不需要交易。

javascript
const factoryAddress = 'z2...'; // 先前创建的工厂地址
const { wallet: issuerWallet } = getIssuerWallet(); // 工厂所有者或受信任的发行方
const { wallet: userWallet } = getUserWallet(); // 将拥有新资产的用户的钱包

async function prepareAssetForMinting() {
  try {
    const mintingData = await client.preMintAsset({
      factory: factoryAddress,
      inputs: {
        attendeeName: 'John Doe',
        ticketType: 'VIP',
      },
      owner: userWallet.address,
      wallet: issuerWallet,
    });

    console.log('Prepared asset data for minting:', mintingData);
    return mintingData;
  } catch (error) {
    console.error('Error preparing asset:', error);
  }
}

步骤 2:发送交易

一旦铸造数据准备好,用户(未来的资产所有者)签名并发送 acquireAsset 交易。来自 preMintAssetitx 对象将用作有效负载。

javascript
async function acquireNewAsset() {
  // 首先,从步骤 1 获取铸造数据
  const itx = await prepareAssetForMinting();
  if (!itx) return;

  try {
    const hash = await client.acquireAsset({
      itx: itx,
      wallet: userWallet, // 用户的钱包签署交易
    });

    console.log(`Asset acquisition transaction sent: ${hash}`);
    console.log(`New asset will be available at address: ${itx.address}`);
  } catch (error) {
    console.error('Error acquiring asset:', error);
  }
}

acquireNewAsset();

acquireAsset 的参数

  • itx object (required) — 从 preMintAsset 方法返回的内部交易对象。
  • wallet WalletObject (required) — 正在获取资产的用户的钱包。
  • delegator string (default: '') — 通过委托授权此交易的账户地址。

返回值

一个 Promise,它会解析为 acquireAsset 操作的交易哈希。

  • response Promise<string> — 交易哈希

从工厂铸造资产

除了用户主导的 acquireAsset 流程外,授权的发行方(例如工厂所有者或受信任的发行方)可以铸造一个资产并将其直接发送到用户的账户。此过程也使用 preMintAsset 来准备数据,但最终的交易是 mintAsset,由发行方签名。

此流程适用于空投、颁发证书或任何接收用户无需发起最终交易的情况。

步骤 1:准备资产数据

此步骤与获取流程相同。发行方调用 preMintAsset 在链下生成交易有效负载(itx)。

javascript
const factoryAddress = 'z2...'; // 工厂地址
const { wallet: issuerWallet } = getIssuerWallet(); // 工厂所有者或受信任的发行方
const userAddress = 'z1...'; // 将接收资产的用户的地址

async function prepareAssetForMinting() {
  try {
    const mintingData = await client.preMintAsset({
      factory: factoryAddress,
      inputs: {
        attendeeName: 'Jane Smith',
        ticketType: 'General',
      },
      owner: userAddress,
      wallet: issuerWallet, // 此处使用发行方的钱包
    });

    console.log('Prepared asset data for minting:', mintingData);
    return mintingData;
  } catch (error) {
    console.error('Error preparing asset:', error);
  }
}

步骤 2:发送铸造交易

发行方使用准备好的 itx 对象调用 mintAsset。交易由发行方的钱包签名,新创建的资产被分配给上一步中指定的所有者。

javascript
async function mintNewAsset() {
  // 首先,从步骤 1 获取铸造数据
  const itx = await prepareAssetForMinting();
  if (!itx) return;

  try {
    // 发行方的钱包签署交易
    const hash = await client.mintAsset({
      itx: itx,
      wallet: issuerWallet,
    });

    console.log(`Asset minting transaction sent: ${hash}`);
    console.log(`New asset for ${userAddress} will be available at address: ${itx.address}`);
  } catch (error) {
    console.error('Error minting asset:', error);
  }
}

mintNewAsset();

mintAsset 的参数

  • itx object (required) — 从 preMintAsset 方法返回的内部交易对象。
  • wallet WalletObject (required) — 正在铸造资产的发行方的钱包。

返回值

一个 Promise,它会解析为 mintAsset 操作的交易哈希。

  • response Promise<string> — 交易哈希