ERC-721 的基架式 TypeScript NFT 项目
Blockchain App Builder 从您的 NFT 规范文件中获取输入,并生成一个功能齐全的支架链代码项目。
该项目自动生成 NFT 生命周期类和函数,包括 CRUD 和非 CRUD 方法,以及标记化 SDK。自动支持参数验证、编集/解编集和透明持久性功能。
有关与 NFT 不直接相关的脚手架项目和方法的信息,请参阅脚手架 TypeScript 链代码项目。
型号
每个标记化模型类都扩展 OchainModel
类。透明持久性功能(Transparent Persistence Capability,简称 ORM)捕获在 OchainModel
类中。
import * as yup from 'yup';
import { Id, Mandatory, Validate, Default, Embedded, Derived, ReadOnly } from '../../lib/decorators';
import { OchainModel } from '../../lib/ochain-model';
import { STRATEGY } from '../../lib/utils';
import { EmbeddedModel } from '../../lib/ochain-embedded-model';
export class ArtCollectionMetadata extends EmbeddedModel<ArtCollectionMetadata> {
@Validate(yup.string())
public painting_name: string;
@Validate(yup.string())
public description: string;
@Validate(yup.string())
public image: string;
@Validate(yup.string())
public painter_name: string;
}
@Id('tokenId')
export class ArtCollection extends OchainModel<ArtCollection> {
public readonly assetType = 'otoken';
@Mandatory()
@Validate(yup.string().required().matches(/^[A-Za-z0-9][A-Za-z0-9_-]*$/).max(16))
public tokenId: string;
@ReadOnly('artcollection')
public tokenName: string;
@Validate(yup.string().trim().max(256))
public tokenDesc: string;
@ReadOnly('ART')
public symbol: string;
@ReadOnly('erc721+')
public tokenStandard: string;
@ReadOnly('nonfungible')
public tokenType: string;
@ReadOnly('whole')
public tokenUnit: string;
@ReadOnly(["indivisible","singleton","mintable","transferable","burnable","roles"])
public behaviors: string[];
@ReadOnly({minter_role_name: "minter"})
public roles: object;
@ReadOnly({max_mint_quantity: 20000})
public mintable: object;
@Validate(yup.string())
public owner: string;
@Validate(yup.string())
public createdBy: string;
@Validate(yup.string())
public transferredBy: string;
@Validate(yup.string())
public creationDate: string;
@Validate(yup.string())
public transferredDate: string;
@Validate(yup.bool())
public isBurned: boolean;
@Validate(yup.string())
public burnedBy: string;
@Validate(yup.string())
public burnedDate: string;
@Validate(yup.string().max(2000))
public tokenUri: string;
@Embedded(ArtCollectionMetadata)
public metadata: ArtCollectionMetadata;
@Validate(yup.number())
public price: number;
@Validate(yup.boolean())
public on_sale_flag: boolean;
}
控制器
主控制器类扩展 OchainController
类。只有一个主控制器。
export class DigiCurrCCController extends OchainController{
可以创建任意数量的类、函数或文件,但只能调用在主控制器类中定义的那些方法。其他方法将被隐藏。
您可以使用令牌 SDK 方法为业务应用程序编写定制方法。
自动生成的 NFT 方法
Blockchain App Builder 自动生成支持 NFT 和 NFT 生命周期的方法。您可以使用这些方法初始化 NFT、管理角色和帐户以及完成其他 NFT 生命周期任务,而无需进行任何其他编码。控制器方法必须具有可调用的 @Validator(...params)
修饰器。
访问控制管理的方法
-
addTokenAdmin
- 此方法将用户添加为链代码的
Token Admin
。此方法只能由链代码的Token Admin
调用。 -
removeTokenAdmin
- 此方法将删除用户作为链代码的
Token Admin
。此方法只能由链代码的Token Admin
调用。 -
isTokenAdmin
- 如果函数的调用方为
Token Admin
,则此方法返回布尔值true
,否则返回false
。Token Admin
可以在区块链网络中的任何其他用户上调用此函数。其他用户只能在自己的帐户上调用此方法。 -
getAllTokenAdmins
- 此方法返回作为链代码
Token Admin
的所有用户的列表。此方法只能由链代码的Token Admin
调用。
标记配置管理的方法
-
init
- 实例化链代码时将调用此方法。每个
Token Admin
都由adminList
参数中的userId
和orgId
信息标识。userId
是实例所有者或登录到实例的用户的用户名或电子邮件 ID。orgId
是当前网络组织中用户的成员服务提供者 (membership service provider,MSP) ID。首次部署链代码时,adminList
参数是必需的。如果要升级链代码,请传递空列表 ([]
)。升级期间将忽略adminList
参数中的任何其他信息。 -
getAllTokens
- 此方法返回在状态数据库中保存的所有标记资产。此方法只能由链代码的
Token Admin
调用。此方法使用 Berkeley DB SQL 富查询,并且只能在连接到远程 Oracle Blockchain Platform 网络时调用。 -
getAllTokensByUser
- 此方法返回指定用户拥有的所有令牌资产。此方法使用 Berkeley DB SQL 富查询,并且只能在连接到远程 Oracle Blockchain Platform 网络时调用。此方法只能由链代码的
Token Admin
或帐户所有者调用。 -
getTokenById
- 如果标记存在于状态数据库中,则此方法返回标记对象。此方法只能由链代码的
Token Admin
或令牌所有者调用。 -
getTokenHistory
- 此方法返回指定标记 ID 的历史记录。这是异步方法。仅当连接到远程 Oracle Blockchain Platform 网络时才能调用此方法。任何人都可以调用此方法。
-
getTokenObject
- 这是返回指定令牌 ID 的令牌实例的实用程序方法。此方法由许多自动生成的方法用于提取令牌对象。可以根据需要从定制方法调用此方法。创建标记化资产或类时,使用相应的
Token
类更新切换大小写以返回正确的标记对象。在规范文件中创建标记化资产时,Blockchain App Builder 中的ochain sync
命令会自动创建切换大小写。此方法没有@Validator()
方法修饰器,这意味着此方法不可直接调用,只能从其他方法调用。 -
ownerOf
- 此方法返回指定令牌 ID 所有者的帐户 ID。任何人都可以调用此方法。
-
name
- 此方法返回令牌类的名称。任何人都可以调用此方法。
-
symbol
- 此方法返回令牌类的符号。任何人都可以调用此方法。
-
tokenURI
- 此方法返回指定令牌的 URI。任何人都可以调用此方法。
-
totalSupply
- 此方法返回铸造标记的总数。此方法只能由链代码的
Token Admin
调用。 -
totalNetSupply
- 此方法返回铸造令牌的总数减去刻录令牌的数量。此方法只能由链代码的
Token Admin
调用。
账户管理方法
-
createAccount
- 此方法为指定的用户和令牌创建帐户。必须为在任何时刻具有令牌的任何用户创建帐户。帐户跟踪用户拥有的 NFT 数量。用户必须在网络中具有帐户才能完成与令牌相关的操作。每个用户只能创建一个 NFT 帐户。
帐户 ID 是字母数字字符集,以
oaccount~
为前缀,后跟当前网络组织中用户的成员服务提供者 ID (orgId
) 的 SHA-256 散列、实例所有者或登录到实例的用户的用户名或电子邮件 ID (userId
) 以及常量字符串nft
。此方法只能由链代码的Token Admin
调用。 -
balanceOf
- 此方法返回指定用户保留的 NFT 的总数。此方法只能由链代码的
Token Admin
或帐户所有者调用。 -
getAllAccounts
- 此方法返回所有帐户的列表。此方法只能由链代码的
Token Admin
调用。此方法使用 Berkeley DB SQL 富查询,并且只能在连接到远程 Oracle Blockchain Platform 网络时调用。 -
getAccountByUser
- 此方法返回指定用户的帐户详细信息。此方法只能由链代码的
Token Admin
或帐户的Account Owner
调用。 -
getUserByAccountId
- 此方法返回指定帐户的用户详细信息。所有用户都可以调用此方法。
-
getAccountHistory
- 此方法返回指定用户的帐户历史记录。这是异步方法。此方法只能由链代码的
Token Admin
或帐户所有者调用。
角色管理的方法
-
addRole
- 此方法向指定用户添加角色。此方法只能由链代码的
Token Admin
调用。 -
removeRole
- 此方法将从指定用户中删除角色。此方法只能由链代码的
Token Admin
调用。 -
getAccountsByRole
- 此方法返回指定角色的所有帐户 ID 的列表。此方法只能由链代码的
Token Admin
调用。 -
getUsersByRole
- 此方法返回指定角色的所有用户的列表。此方法只能由链代码的
Token Admin
调用。 -
isInRole
- 此方法返回布尔值以指示用户是否具有指定的角色。此方法只能由链代码的
Token Admin
或帐户的Account Owner
调用。
事务处理历史记录管理方法
-
getAccountTransactionHistory
- 此方法返回指定用户的账户事务处理历史记录。这是异步方法。此方法只能由链代码的
Token Admin
或帐户所有者调用。 -
getAccountTransactionHistoryWithFilters
- 此方法返回指定用户的帐户事务处理历史记录,筛选条件为
PageSize
、Bookmark
、startTime
和endTime
。这是异步方法。仅当连接到远程 Oracle Blockchain Platform 网络时才能调用此方法。此方法只能由链代码的Token Admin
或帐户所有者调用。 -
getTransactionById
- 此方法返回指定事务处理 ID 的事务处理历史记录。这是异步方法。此方法只能由链代码的
Token Admin
或帐户所有者调用。 -
deleteHistoricalTransactions
- 此方法删除状态数据库中早于指定时间戳的事务处理。这是异步方法。此方法只能由链代码的
Token Admin
调用。
标记行为管理的方法 - 可最小化行为
-
create<Token Name>Token
- 此方法创建(薄荷)NFT。资产和关联属性保存在状态数据库中。此事务处理的调用方必须具有令牌账户。此事务处理的调用者将成为 NFT 的所有者。如果令牌规范文件包括
behaviors
的roles
部分和roles
的minter_role_name
属性,则事务处理的调用方必须具有 minter 角色。否则,任何调用方都可以创建 NFT。 -
update<Token Name>Token
- 此方法更新令牌属性。此方法只能由作为令牌的所有者或创建者的用户调用。创建令牌资产后,只有令牌所有者才能更新令牌定制属性。如果用户既是令牌所有者,又是令牌的创建者,他们还可以更新
TokenDesc
属性。无法更新令牌元数据。必须将所有标记属性传递到此方法,即使您只希望更新某些属性也是如此。
标记行为管理的方法 - 可传输行为
-
safeTransferFrom
- 这是一个异步函数。此方法将指定 NFT 的所有权从调用方转移到另一个帐户。此方法包括以下验证:
- 代币存在且未被烧毁。
- 发件人账户和接收者账户存在且不是同一账户。
- 发件人账户拥有令牌。
- 函数的调用方是发送方。
-
transferFrom
- 这是一个异步函数。此方法将指定 NFT 的所有权从发送方帐户转移至接收方帐户。调用方有责任传递正确的参数。此方法可由任何用户调用,而不仅仅是令牌所有者。此方法包括以下验证:
- 代币存在且未被烧毁。
- 发件人账户和接收者账户存在且不是同一账户。
- 发件人账户拥有令牌。
标记行为管理的方法 - 可刻录行为
-
burn
- 此方法从调用者的帐户中停用或消耗指定的 NFT。此方法的调用方必须具有帐户。除非令牌规范文件包含
burnable
行为,否则无法刻录令牌。如果在规范文件的roles
部分中未指定burner_role_name
属性,则令牌的所有者可以刻录令牌。如果在roles
部分中指定了burner_role_name
属性,则指定燃烧者角色的用户(也是令牌的矿工(创建者)或所有者)可以刻录令牌。 -
burnNFT
- 此方法从调用者的帐户中停用或消耗指定的 NFT,并返回令牌对象和令牌历史记录。此方法的调用方必须具有帐户。除非令牌规范文件包含
burnable
行为,否则无法刻录令牌。如果在规范文件的roles
部分中未指定burner_role_name
属性,则令牌的所有者可以刻录令牌。如果在roles
部分中指定了burner_role_name
属性,则指定燃烧者角色的用户(也是令牌的矿工(创建者)或所有者)可以刻录令牌。
定制方法
您可以使用令牌 SDK 方法为业务应用程序编写定制方法。
以下示例说明如何在定制方法中使用标记 SDK 方法。调用 sell
方法时,会以指定价格发布要销售的令牌。
@Validator(yup.string(), yup.number())
public async sell(token_id: string, selling_price: number) {
try {
const token = await this.Ctx.ERC721Token.get(token_id);
const t = new ArtCollection(token)
/** * price is a custom asset
attribute to set the price of a non-fungible token in the
marketplace */
t.price = selling_price;
/** * on_sale_flag is a
custom asset attribute that maintains non-fungible token selling status in the
marketplace */
t.on_sale_flag = true;
await this.Ctx.ERC721Token.updateToken(t);
let msg = `Token ID : '${token_id}' has been posted for selling in the marketplace'`;
return {msg}
} catch(error) {
throw new Error(error.message);
}
}
NFT SDK 方法
访问控制管理的方法
Token Admin
或 Account Owner
调用。您可以使用此功能确保仅由目标用户执行操作。任何未经授权的访问都会导致错误。要使用访问控制功能,请从 ../lib/erc721-auth
模块导入 Authorization
类。import { ERC721Authorization } from '../lib/erc721-auth';
-
checkAuthorization
- 使用此方法可将访问控制检查添加到操作。这是一个异步函数。大多数自动生成的方法都包括访问控制。对于具有多个帐户的用户,某些令牌方法只能由令牌的
ERC721Admin
或Account Owner
或MultipleAccountOwner
运行。checkAuthorization
方法是Authorization
类的一部分,可通过Ctx
对象访问该类。访问控制映射在../lib/constant.ts
文件中进行了介绍,如以下文本所示。可以通过编辑../lib/constant.ts
文件来修改访问控制。要使用您自己的访问控制或禁用访问控制,请从自动生成的控制器方法和定制方法中删除访问控制代码。export const TOKENACCESS = { ADMIN: { isUserTokenAdmin: ['Admin', 'MultipleAccountOwner'], addAdmin: ['Admin'], removeAdmin: ['Admin'], getAllAdmins: ['Admin'], }, TOKEN: { save: ['Admin'], getAllTokens: ['Admin'], get: ['Admin'], update: ['Admin'], getDecimals: ['Admin'], getTokensByName: ['Admin'], addRoleMember: ['Admin'], removeRoleMember: ['Admin'], isInRole: ['Admin', 'AccountOwner'], getTotalMintedTokens: ['Admin'], getNetTokens: ['Admin'], }, ROLE: { getAccountsByRole: ['Admin'], getUsersByRole: ['Admin'], }, TRANSACTION: { deleteTransactions: ['Admin'], }, ACCOUNT: { createAccount: ['Admin'], getAllAccounts: ['Admin'], getAccountsByUser: ['Admin', 'MultipleAccountOwner'], getAccount: ['Admin', 'AccountOwner'], history: ['Admin', 'AccountOwner'], getAccountTransactionHistory: ['Admin', 'AccountOwner'], getAccountBalance: ['Admin', 'AccountOwner'], getAccountOnHoldBalance: ['Admin', 'AccountOwner'], getOnHoldIds: ['Admin', 'AccountOwner'], }, ERC721ADMIN: { isUserTokenAdmin: ['Admin'], addAdmin: ['Admin'], removeAdmin: ['Admin'], getAllAdmins: ['Admin'], }, ERC721TOKEN: { getAllTokens: ['Admin'], getAllTokensByUser: ['Admin', 'AccountOwner'], get: ['Admin', TOKEN_OWNER], getTokensByName: ['Admin'], addRoleMember: ['Admin'], removeRoleMember: ['Admin'], isInRole: ['Admin', 'AccountOwner'], totalSupply: ['Admin'], totalNetSupply: ['Admin'], history: ['Admin'], }, ERC721ROLE: { getAccountsByRole: ['Admin'], getUsersByRole: ['Admin'], }, ERC721TRANSACTION: { deleteTransactions: ['Admin'], }, ERC721ACCOUNT: { createAccount: ['Admin'], getAllAccounts: ['Admin'], getAccountsByUser: ['Admin', 'MultipleAccountOwner'], history: ['Admin', 'AccountOwner'], getAccountTransactionHistory: ['Admin', 'AccountOwner'], getAccountTransactionHistoryWithFilters: ['Admin', 'AccountOwner'], balanceOf: ['Admin', 'MultipleAccountOwner'], } }
-
isUserTokenAdmin
- 如果函数的调用方为
Token Admin
,则此方法返回布尔值true
。否则,方法返回false
。这是异步静态函数。 -
addAdmin
- 此方法将用户添加为令牌链代码的
Token Admin
。 -
removeAdmin
- 此方法将删除用户作为标记链代码的
Token Admin
。 -
getAllAdmins
- 此方法返回所有
Token Admin
用户的列表。
标记配置管理的方法
令牌配置管理方法基于 ERC-721 标准。要使用令牌配置管理方法,请从 ../lib/erc721-token
模块导入 Token
类。
-
totalSupply
- 此方法返回铸造 NFT 的总数。这是一个异步函数。
-
get
- 如果指定的标记对象存在于状态数据库中,则此方法返回该对象。这是异步静态函数。
-
isTokenType
- 此方法指示是否存在具有指定 ID 的标记资产。这是异步静态函数。
-
createToken
- 此方法创建令牌并将其属性保存在状态数据库中。此方法只能由具有 minter 角色的用户调用。这是一个异步函数。
-
updateToken
- 此方法更新令牌属性。此方法只能由令牌的所有者或创建者调用。创建令牌资产后,只有令牌所有者才能更新令牌定制属性。如果用户既是令牌所有者,又是令牌的创建者,他们还可以更新
TokenDesc
属性。无法更新令牌元数据。必须将所有标记属性传递到此方法,即使您只希望更新某些属性也是如此。这是一个异步函数。 -
getByRange
- 此方法在内部调用网状结构网络
getStateByRange
方法。即使从分类账返回具有给定 ID 的任何资产,此方法仍会将资产强制转换为调用方资产类型。这是异步静态函数。@validator(yup.string(), yup.string()) public async getDigiCurrGetByRange(startId: string, endId: string) { return await this.Ctx.ERC721TOken.getByRange(startId, endId, PaintingNft); }
-
history
- 此方法返回指定标记的历史记录。这是异步静态函数。
-
getAllTokens
- 此方法返回在状态数据库中保存的所有标记资产。此方法使用 Berkeley DB SQL 富查询,并且只能在连接到远程 Oracle Blockchain Platform 网络时调用。这是异步静态函数。
-
getAllTokensByUser
- 此方法返回指定帐户 ID 拥有的所有令牌。这是异步静态函数。
-
ownerOf
- 此方法返回指定标记所有者的帐户 ID。这是异步静态函数。
-
tokenUri
- 此方法返回指定令牌的 URI。这是异步静态函数。
-
getTokenUri
- 此方法返回指定令牌的 URI。这是异步静态函数。
-
symbol
- 此方法返回令牌类的符号。
账户管理方法
-
generateAccountId
- 此方法返回帐户 ID,该 ID 通过连接成员服务提供者 ID (
orgId
) 和用户名或电子邮件 ID (userId
),然后创建 SHA-256 散列来形成。 -
createAccount
- 此方法为指定的用户和令牌创建帐户。必须为在任何时刻具有令牌的任何用户创建帐户。帐户跟踪用户拥有的 NFT 数量。用户必须在网络中具有帐户才能完成与令牌相关的操作。每个用户只能创建一个 NFT 帐户。
帐户 ID 是字母数字字符集,以
oaccount~
为前缀,后跟当前网络组织中用户的成员服务提供者 ID (orgId
) 的 SHA-256 散列、实例所有者或登录到实例的用户的用户名或电子邮件 ID (userId
) 以及常量字符串nft
。此方法只能由链代码的Token Admin
调用。 -
getAllAccounts
- 此方法返回所有帐户的列表。此方法使用 Berkeley DB SQL 富查询,并且只能在连接到远程 Oracle Blockchain Platform 网络时调用。
-
history
- 此方法返回指定帐户的帐户历史记录详细信息数组。
-
getUserByAccountId
- 此方法返回指定帐户的用户详细信息。
-
getAccountWithStatusByUser
- 此方法返回指定帐户的用户详细信息,包括帐户状态。此方法只能由链代码的
Token Admin
或帐户的Account Owner
调用。 -
getAccountByUser
- 此方法返回指定帐户的用户详细信息。此方法只能由链代码的
Token Admin
或帐户的Account Owner
调用。 -
balanceOf
- 此方法返回指定用户保留的 NFT 的总数。
角色管理的方法
-
addRoleMember
- 此方法向指定用户和令牌添加角色。帐户 ID 是通过创建串联成员服务供应商 ID (
orgId
) 和用户名或电子邮件 ID (userId
) 的 SHA-256 散列形成的。这是一个异步函数。 -
removeRoleMember
- 此方法将从指定用户和令牌中删除角色。帐户 ID 是通过创建串联成员服务供应商 ID (
orgId
) 和用户名或电子邮件 ID (userId
) 的 SHA-256 散列形成的。这是一个异步函数。 -
isInRole
- 此方法返回布尔值以指示用户和令牌是否具有指定的角色。帐户 ID 是通过创建串联成员服务供应商 ID (
orgId
) 和用户名或电子邮件 ID (userId
) 的 SHA-256 散列形成的。这是一个异步函数。 -
getAccountsByRole
- 此方法返回指定角色的所有帐户 ID 的列表。
-
getUsersByRole
- 此方法返回指定角色的所有用户的列表。
事务处理历史记录管理方法
-
getAccountTransactionHistory
- 此方法返回指定账户的事务处理历史记录详细信息数组。
-
getAccountTransactionHistoryWithFilters
- 此方法返回指定用户的帐户事务处理历史记录,筛选条件为
PageSize
、Bookmark
、startTime
和endTime
。仅当连接到远程 Oracle Blockchain Platform 网络时才能调用此方法。 -
getTransactionById
- 此方法返回
Transaction
资产的历史记录。 -
deleteHistoricalTransactions
- 此方法将从状态数据库中删除早于指定日期的事务处理。
标记行为管理 - Mintable Behavior
-
getMaxMintQuantity
- 此方法返回标记的最大可最小数量。如果未在规范文件中配置
max_mint_quantity
行为,则默认值为 0,并且可以铸造无限数量的标记。 -
getTotalMintedTokens
- 此方法返回系统中可用于指定标记的总铸造标记数。可用令牌的净数量是铸造令牌的总数减去烧毁令牌的数量。这是一个异步函数。
标记行为管理 - 可转移行为
-
safeTransferFrom
- 这是一个异步函数。此方法将指定 NFT 的所有权从调用方转移到另一个帐户。此方法包括以下验证:
- 代币存在且未被烧毁。
- 发件人账户和接收者账户存在且不是同一账户。
- 发件人账户拥有令牌。
- 函数的调用方是发送方。
-
transferFrom
- 这是一个异步函数。此方法将指定 NFT 的所有权从发送方帐户转移至接收方帐户。调用方有责任传递正确的参数。此方法可由任何用户调用,而不仅仅是令牌所有者。此方法包括以下验证:
- 代币存在且未被烧毁。
- 发件人账户和接收者账户存在且不是同一账户。
- 发件人账户拥有令牌。
标记行为管理 - 可刻录行为