The NFTModule is used for creating, destroying NFTs (non-fungible tokens), and transferring them in the Lisk ecosystem.

Not a stand-alone module

The NFT module is not intended to be used as a stand-alone module. Instead, it should be used inside other modules, that intend to implement features related to NFTs. Other modules can use the provided methods of the NFT module, to implement custom commands for minting and destroying NFTs in the network. This allows to define the specific details about how NFTs are created, and who is allowed to mint them.

NFT Identifier

To identify NFTs in the Lisk ecosystem, we introduce the nftID, a unique NFT identifier in the ecosystem. It is a 16 bytes long concatenation of the 4 bytes long chainID, the chain ID of the chain creating the NFT, the 4 bytes long collectionID, chosen when the NFT is created, and an 8 bytes long serialization of an index integer, automatically assigned at the NFT creation.

This allows chains to define multiple sets of NFTs, each identified by their respective collection. Each collection can then easily have its own attributes schema and custom logic. For example, an art NFT exchange could have a different collection per artist, the index being a unique integer associated with each art piece of this artist.


Each NFT is stored with an array of attributes specified by various modules, with each attribute property being a byte sequence that is not deserialized by the NFT module. Each custom module using NFTs should define schemas to serialize and deserialize their attributes property of NFTs.

Note that the attributes properties are not limited in size by default, which can potentially cause the CCM validateFormat failure during the cross-chain NFT transfer.

When an NFT is sent to another chain, the attributes properties of the NFT can be modified according to specifications set on the receiving chain. When the NFT is received back on its native chain, the returned modified attributes are disregarded and the original attributes are restored, as currently defined by getNewAttributes function. If needed, custom modules can implement a more fine-grained approach towards the attributes that are modified cross-chain.

NFT cross-chain transfers

As is the case with fungible tokens, all NFTs are escrowed in the native chain. Technically, this means that when a token is sent from its native chain to another, the NFT is not erased, but the owner of the NFT now becomes the receiving chain. When an NFT is returned, the native chain can then check that the NFT is indeed coming from the chain it was sent to and was not maliciously created and transferred from another chain. This implies that NFTs can only be transferred to and from their native chain.


LIP 0052 - Introduce NFT module




_ccTransferCommand: Modules.NFT.TransferCrossChainCommand = ...
_feeMethod: FeeMethod
_internalMethod: InternalMethod = ...
_interoperabilityMethod: InteroperabilityMethod
_tokenMethod: TokenMethod
_transferCommand: Modules.NFT.TransferCommand = ...

A command is a group of state-transition logic triggered by a transaction and is identified by the module and command name of the transaction.

crossChainCommand: Modules.NFT.CrossChainTransferCommand[] = ...

A list of the cross-chain commands of the module

crossChainMethod: NFTInteroperableMethod = ...

Methods related to cross-chain communication

crossChainTransferCommand: Modules.NFT.CrossChainTransferCommand = ...
endpoint: NFTEndpoint = ...

An endpoint is an interface between a module and an external system. Lisk endpoints support RPC communication. The module-specific RPC endpoints can be invoked by external services, like UIs, to get relevant data from the application.

Endpoints allow us to conveniently get data from the blockchain. It is never possible to set data / mutate the state via module endpoints.

events: NamedRegistry = ...

Blockchain events, or module events, are logs of events that occur in the blockchain network during block execution. Events occur per block, and are stored in the respective block header, from where they can be queried.

method: NFTMethod = ...

A method is an interface for module-to-module communication, and can perform state mutations on the blockchain.

To get or set module-specific data in the blockchain, methods are either called by other modules or by the module itself. For example, the transfer() method from the Token module is called by a module, if it needs to transfer tokens from one account to the other.

offchainStores: NamedRegistry = ...

In a module, the off-chain store is available in: insertAssets & Endpoints.

It complements the on-chain module store, by allowing to store various additional data in the blockchain client, that does not need to be included in the on-chain store.

The data stored in the off-chain store is not part of the blockchain protocol, and it may differ from machine to machine.

stores: NamedRegistry = ...

A module can define one or multiple on-chain stores, to store data in the blockchain, i.e. to include it in the blockchain state.

For example, data such as account balances, validator’s names, and multisignature keys are values that are stored in the on-chain module store.



  • Returns {
        assets: never[];
        commands: {
            name: string;
            params: Schema;
        endpoints: never[];
        events: {
            data: Schema;
            name: string;
        stores: {
            data: Schema;
            key: string;

    • assets: never[]
    • commands: {
          name: string;
          params: Schema;
    • endpoints: never[]
    • events: {
          data: Schema;
          name: string;
    • stores: {
          data: Schema;
          key: string;

Generated using TypeDoc