Scaffolded TypeScript NFT Project for ERC-721
Blockchain App Builder takes the input from your NFT specification file and generates a fully-functional scaffolded chaincode project.
The project automatically generates NFT lifecycle classes and functions, including CRUD and non-CRUD methods, as well as a tokenization SDK. Validation of arguments, marshalling/unmarshalling, and transparent persistence capability are all supported automatically.
For information on the scaffolded project and methods that are not directly related to NFTs, see Scaffolded TypeScript Chaincode Project.
Model
Every tokenized model class extends the OchainModel
class. Transparent Persistence Capability, or simplified ORM, is captured in the
OchainModel
class.
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;
}
Controller
The main controller class extends the OchainController
class. There is only one main controller.
export class DigiCurrCCController extends OchainController{
You can create any number of classes, functions, or files, but only those methods that are defined within the main controller class are invokable. The other methods are hidden.
You can use the token SDK methods to write custom methods for your business application.
Automatically Generated NFT Methods
Blockchain App Builder automatically generates methods to support NFTs
and NFT life cycles. You can use these methods to initialize NFTs, manage roles and
accounts, and complete other NFT lifecycle tasks without any additional coding.
Controller methods must have a @Validator(...params)
decorator to
be invokable.
- Access Control Management
- Token Configuration Management
- Account Management
- Role Management
- Transaction History Management
- Token Behavior Management
Methods for Access Control Management
-
addTokenAdmin
- This method adds a user as a
Token Admin
of the chaincode. This method can be called only by aToken Admin
of the chaincode. -
removeTokenAdmin
- This method removes a user as a
Token Admin
of the chaincode. This method can be called only by aToken Admin
of the chaincode. -
isTokenAdmin
- This method returns the Boolean value
true
if the caller of the function is aToken Admin
, otherwise it returnsfalse
. AToken Admin
can call this function on any other user in the blockchain network. Other users can call this method only on their own accounts. -
getAllTokenAdmins
- This method returns a list of all users who are a
Token Admin
of the chaincode. This method can be called only by theToken Admin
of the chaincode.
Methods for Token Configuration Management
-
init
- This method is called when the chaincode is instantiated. Every
Token Admin
is identified by theuserId
andorgId
information in theadminList
parameter. TheuserId
is the user name or email ID of the instance owner or the user who is logged in to the instance. TheorgId
is the membership service provider (MSP) ID of the user in the current network organization. TheadminList
parameter is mandatory the first time you deploy the chaincode. If you are upgrading the chaincode, pass an empty list ([]
). Any other information in theadminList
parameter is ignored during upgrades. -
getAllTokens
- This method returns all of the token assets that are saved in
the state database. This method can be called only by a
Token Admin
of the chaincode. This method uses Berkeley DB SQL rich queries and can only be called when connected to the remote Oracle Blockchain Platform network. -
getAllTokensByUser
- This method returns all of the token assets that are owned by a
specified user. This method uses Berkeley DB SQL rich queries and can only
be called when connected to the remote Oracle Blockchain Platform network.
This method can be called only by a
Token Admin
of the chaincode or by the account owner. -
getTokenById
- This method returns a token object if the token is present in
the state database. This method can be called only by a
Token Admin
of the chaincode or the token owner. -
getTokenHistory
- This method returns the history for a specified token ID. This is an asynchronous method. This method can only be called when connected to the remote Oracle Blockchain Platform network. Anyone can call this method.
-
getTokenObject
- This is a utility method that returns an instance of the token
for a specified token ID. This method is used by many of the automatically
generated methods to fetch token objects. You can call this method as needed
from your custom methods. When you create a tokenized asset or class, update
the switch case with the corresponding
Token
class to return the correct token object. Theochain sync
command in Blockchain App Builder automatically creates a switch case when a tokenized asset is created in the specification file. This method has no@Validator()
method decorator, which means this method is not directly invokable and can only be called from other methods. -
ownerOf
- This method returns the account ID of the owner of the specified token ID. Anyone can call this method.
-
name
- This method returns the name of the token class. Anyone can call this method.
-
symbol
- This method returns the symbol of the token class. Anyone can call this method.
-
tokenURI
- This method returns the URI of a specified token. Anyone can call this method.
-
totalSupply
- This method returns the total number of minted tokens. This
method can be called only by a
Token Admin
of the chaincode. -
totalNetSupply
- This method returns the total number of minted tokens minus the
number of burned tokens. This method can be called only by a
Token Admin
of the chaincode.
Methods for Account Management
-
createAccount
- This method creates an account for a specified user and token.
An account must be created for any user who will have tokens at any point.
Accounts track the number of NFTs a user has. Users must have accounts in
the network to complete token-related operations. You can create only one
NFT account per user.
An account ID is an alphanumeric set of characters, prefixed with
oaccount~
and followed by an SHA-256 hash of the membership service provider ID (orgId
) of the user in the current network organization, the user name or email ID (userId
) of the instance owner or the user who is logged in to the instance, and the constant stringnft
. This method can be called only by theToken Admin
of the chaincode. -
balanceOf
- This method returns the total number of NFTs that a specified
user holds. This method can be called only by a
Token Admin
of the chaincode or by the account owner. -
getAllAccounts
- This method returns a list of all accounts. This method can be
called only by a
Token Admin
of the chaincode. This method uses Berkeley DB SQL rich queries and can only be called when connected to the remote Oracle Blockchain Platform network. -
getAccountByUser
- This method returns account details for a specified user. This
method can be called only by a
Token Admin
of the chaincode or theAccount Owner
of the account. -
getUserByAccountId
- This method returns the user details of a specified account. This method can be called by any user.
-
getAccountHistory
- This method returns account history for a specified user. This
is an asynchronous method. This method can be called only by the
Token Admin
of the chaincode or by the account owner.
Methods for Role Management
-
addRole
- This method adds a role to a specified user. This method can be
called only by a
Token Admin
of the chaincode. -
removeRole
- This method removes a role from a specified user. This method
can be called only by a
Token Admin
of the chaincode. -
getAccountsByRole
- This method returns a list of all account IDs for a specified
role. This method can be called only by a
Token Admin
of the chaincode. -
getUsersByRole
- This method returns a list of all users for a specified role.
This method can be called only by a
Token Admin
of the chaincode. -
isInRole
- This method returns a Boolean value to indicate if a user has a
specified role. This method can be called only by a
Token Admin
of the chaincode or theAccount Owner
of the account.
Methods for Transaction History Management
-
getAccountTransactionHistory
- This method returns account transaction history for a specified
user. This is an asynchronous method. This method can be called only by the
Token Admin
of the chaincode or by the account owner. -
getAccountTransactionHistoryWithFilters
- This method returns account transaction history for a specified
user, filtered by
PageSize
,Bookmark
,startTime
andendTime
. This is an asynchronous method. This method can only be called when connected to the remote Oracle Blockchain Platform network. This method can be called only by theToken Admin
of the chaincode or by the account owner. -
getTransactionById
- This method returns transaction
history for a specified transaction ID. This is an asynchronous method. This
method can be called only by a
Token Admin
of the chaincode or by the account owner. -
deleteHistoricalTransactions
- This method deletes transactions older than a specified time
stamp in the state database. This is an asynchronous method. This method can
be called only by a
Token Admin
of the chaincode.
Methods for Token Behavior Management - Mintable Behavior
-
create<Token Name>Token
- This method creates (mints) an NFT. The asset and associated
properties are saved in the state database. The caller of this transaction
must have a token account. The caller of this transaction becomes the owner
of the NFT. If the token specification file includes the
roles
section forbehaviors
and theminter_role_name
property forroles
, then the caller of the transaction must have the minter role. Otherwise, any caller can mint NFTs. -
update<Token Name>Token
- This method updates token properties. This method can be called
only by the user who is the owner or creator of the token. After a token
asset is created, only the token owner can update the token custom
properties.
If
the user is both token owner and creator of a token, they can also update
the
TokenDesc
property. Token metadata cannot be updated. You must pass all token properties to this method, even if you want to update only certain properties.
Methods for Token Behavior Management - Transferable Behavior
-
safeTransferFrom
- This is an asynchronous function. This method transfers
ownership of the specified NFT from the caller to another account. This
method includes the following validations:
- The token exists and is not burned.
- The sender account and receiver account exist and are not the same account.
- The sender account owns the token.
- The caller of the function is the sender.
-
transferFrom
- This is an asynchronous function. This method transfers
ownership of the specified NFT from a sender account to a receiver account.
It is the responsibility of the caller to pass the correct parameters. This
method can be called by any user, not only the token owner. This method
includes the following validations:
- The token exists and is not burned.
- The sender account and receiver account exist and are not the same account.
- The sender account owns the token.
Methods for Token Behavior Management - Burnable Behavior
-
burn
- This method deactivates, or burns, the specified NFT from the
caller's account. The caller of this method must have an account. A token
cannot be burned unless the token specification file includes the
burnable
behavior. If noburner_role_name
property is specified in theroles
section of the specification file, then the owner of the token can burn the token. If aburner_role_name
property is specified in theroles
section, then the user assigned the burner role who is also the minter (creator) or owner of the token can burn the token. -
burnNFT
- This method deactivates, or burns, the specified NFT from the
caller's account, and returns a token object and token history. The caller
of this method must have an account. A token cannot be burned unless the
token specification file includes the
burnable
behavior. If noburner_role_name
property is specified in theroles
section of the specification file, then the owner of the token can burn the token. If aburner_role_name
property is specified in theroles
section, then the user assigned the burner role who is also the minter (creator) or owner of the token can burn the token.
Custom Methods
You can use the token SDK methods to write custom methods for your business application.
The following example shows how to use token SDK methods in custom
methods. When the sell
method is called, it posts a token for sale
for a specified price.
@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 Methods
- Access Control Management
- Token Configuration Management
- Account Management
- Role Management
- Transaction History Management
- Token Behavior Management
Methods for Access Control Management
Token Admin
or Account Owner
of
the token. You can use this feature to ensure that operations are carried out only
by the intended users. Any unauthorized access results in an error. To use the
access control function, import the Authorization
class from the
../lib/erc721-auth
module.import { ERC721Authorization } from '../lib/erc721-auth';
-
checkAuthorization
- Use this method to add an access control check to an operation.
This is an asynchronous function. Most automatically generated methods
include access control. Certain token methods can be run only by the
ERC721Admin
orAccount Owner
of the token or by theMultipleAccountOwner
for users with multiple accounts. ThecheckAuthorization
method is part of theAuthorization
class, which you access via theCtx
object. The access control mapping is described in the../lib/constant.ts
file, as shown in the following text. You can modify access control by editing the../lib/constant.ts
file. To use your own access control or to disable access control, remove the access control code from the automatically generated controller methods and custom methods.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
- This method returns the Boolean value
true
if the caller of the function is aToken Admin
. Otherwise the method returnsfalse
. This is an asynchronous static function. -
addAdmin
- This method adds a user as a
Token Admin
of the token chaincode. -
removeAdmin
- This method removes a user as a
Token Admin
of the token chaincode. -
getAllAdmins
- This method returns a list of all
Token Admin
users.
Methods for Token Configuration Management
The token configuration management methods are based on the ERC-721
standard. To use the token configuration management methods, import the
Token
class from the ../lib/erc721-token
module.
-
totalSupply
- This method returns the total number of minted NFTs. This is an asynchronous function.
-
get
- This method returns the specified token object if it is present in the state database. This is an asynchronous static function.
-
isTokenType
- This method indicates whether a token asset exists with the specified ID. This is an asynchronous static function.
-
createToken
- This method creates a token and saves its properties in the state database. This method can be called only by users with the minter role. This is an asynchronous function.
-
updateToken
- This method updates token properties. This method can be called
only by the owner or creator of the token. After a token asset is created,
only the token owner can update the token custom properties. If the user is
both token owner and creator of a token, they can also update the
TokenDesc
property. Token metadata cannot be updated. You must pass all token properties to this method, even if you want to update only certain properties. This is an asynchronous function. -
getByRange
- This method calls the fabric
getStateByRange
method internally. Even though any asset with the given ID is returned from the ledger, this method casts the asset into the caller Asset type. This is an asynchronous static function.@validator(yup.string(), yup.string()) public async getDigiCurrGetByRange(startId: string, endId: string) { return await this.Ctx.ERC721TOken.getByRange(startId, endId, PaintingNft); }
-
history
- This method returns history for the specified token. This is an asynchronous static function.
-
getAllTokens
- This method returns all of the token assets that are saved in the state database. This method uses Berkeley DB SQL rich queries and can only be called when connected to the remote Oracle Blockchain Platform network. This is an asynchronous static function.
-
getAllTokensByUser
- This method returns all tokens that are owned by a specified account ID. This is an asynchronous static function.
-
ownerOf
- This method returns the account ID of the owner of a specified token. This is an asynchronous static function.
-
tokenUri
- This method returns the URI for a specified token. This is an asynchronous static function.
-
getTokenUri
- This method returns the URI for a specified token. This is an asynchronous static function.
-
symbol
- This method returns the symbol of the token class.
Methods for Account Management
-
generateAccountId
- This method returns an account ID, which is formed by
concatenating the membership service provider ID (
orgId
) and the user name or email ID (userId
) and then creating a SHA-256 hash. -
createAccount
- This method creates an account for a specified user and token.
An account must be created for any user who will have tokens at any point.
Accounts track the number of NFTs a user has. Users must have accounts in
the network to complete token-related operations. You can create only one
NFT account per user.
An account ID is an alphanumeric set of characters, prefixed with
oaccount~
and followed by an SHA-256 hash of the membership service provider ID (orgId
) of the user in the current network organization, the user name or email ID (userId
) of the instance owner or the user who is logged in to the instance, and the constant stringnft
. This method can be called only by theToken Admin
of the chaincode. -
getAllAccounts
- This method returns a list of all accounts. This method uses Berkeley DB SQL rich queries and can only be called when connected to the remote Oracle Blockchain Platform network.
-
history
- This method returns an array of the account history details for a specified account.
-
getUserByAccountId
- This method returns the user details for a specified account.
-
getAccountWithStatusByUser
- This method returns user details for a specified account,
including account status. This method can be called only by a
Token Admin
of the chaincode or theAccount Owner
of the account. -
getAccountByUser
- This method returns user details for a specified account. This
method can be called only by a
Token Admin
of the chaincode or theAccount Owner
of the account. -
balanceOf
- This method returns the total number of NFTs the specified user holds.
Methods for Role Management
-
addRoleMember
- This method adds a role to a specified user and token. An
account ID is formed by creating an SHA-256 hash of the concatenated
membership service provider ID (
orgId
) and the user name or email ID (userId
). This is an asynchronous function. -
removeRoleMember
- This method removes a role from a specified user and token. An
account ID is formed by creating an SHA-256 hash of the concatenated
membership service provider ID (
orgId
) and the user name or email ID (userId
). This is an asynchronous function. -
isInRole
- This method returns a Boolean value to indicate if a user and
token has a specified role. An account ID is formed by creating an SHA-256
hash of the concatenated membership service provider ID
(
orgId
) and the user name or email ID (userId
). This is an asynchronous function. -
getAccountsByRole
- This method returns a list of all account IDs for a specified role.
-
getUsersByRole
- This method returns a list of all users for a specified role.
Methods for Transaction History Management
-
getAccountTransactionHistory
- This method returns an array of the transaction history details for a specified account.
-
getAccountTransactionHistoryWithFilters
- This method returns account transaction history for a specified
user, filtered by
PageSize
,Bookmark
,startTime
andendTime
. This method can only be called when connected to the remote Oracle Blockchain Platform network. -
getTransactionById
- This method returns the history of a
Transaction
asset. -
deleteHistoricalTransactions
- This method deletes transactions that are older than a specified date from the state database.
Token Behavior Management - Mintable Behavior
-
getMaxMintQuantity
- This method returns the maximum mintable quantity of a token. If
the
max_mint_quantity
behavior is not configured in the specification file, then the default value is 0 and an infinite number of tokens can be minted. -
getTotalMintedTokens
- This method returns the total minted number of tokens available in the system for the specified token. The net number of tokens available is the total number of minted tokens minus the number of burned tokens. This is an asynchronous function.
Token Behavior Management - Transferable Behavior
-
safeTransferFrom
- This is an asynchronous function. This method transfers
ownership of the specified NFT from the caller to another account. This
method includes the following validations:
- The token exists and is not burned.
- The sender account and receiver account exist and are not the same account.
- The sender account owns the token.
- The caller of the function is the sender.
-
transferFrom
- This is an asynchronous function. This method transfers
ownership of the specified NFT from a sender account to a receiver account.
It is the responsibility of the caller to pass the correct parameters. This
method can be called by any user, not only the token owner. This method
includes the following validations:
- The token exists and is not burned.
- The sender account and receiver account exist and are not the same account.
- The sender account owns the token.
Token Behavior Management - Burnable Behavior
-
burn
- This method deactivates, or burns, the specified NFT from the
caller's account. The caller of this method must have an account. A token
cannot be burned unless the token specification file includes the
burnable
behavior. If noburner_role_name
property is specified in theroles
section of the specification file, then the owner of the token can burn the token. If aburner_role_name
property is specified in theroles
section, then the user assigned the burner role who is also the minter (creator) of the token can burn the token. This is an asynchronous function.