This implementation of the standard aims to make development on Nervos Layer 1 easier and more secure by leveraging the use of a core with the basic standard features, plus extensions that can easily be added to give each application custom behavior. This core and extensions are previously tested and audited, speeding up new developments while maintaining security and reliability.
Blockchain development in Layer 1 of Nervos ecosystem is accomplished through low-level languages, mainly RUST. This allows for efficient and compact code, but can substantially increase the onboarding time when developers arrive at this ecosystem.
To help speed up the onboarding of new developers and simplify the work for the experienced ones, we propose the following code structure that leverages the use of metaprogramming to build modular scripts that can be adapted to specific use cases while maintaining efficiency and security.
Rust implementation
Our implementation consists of two repositories: NRC-721 and NRC-721-template. The first one contains the base implementation of the type-script for a custom NFT. It also contains optional behaviors that can be added using a single line of code, increasing the capabilities of the NRC-721. The second repository contains a template for creating custom NFTs.
Custom NFT creation procedure
In order to compile the custom NFT, it is necessary to have ckb-capsule installed and working.
Then the following steps will suffice to edit and build a new NFT.
First, we need to clone the NRC-721-template repository. Then, to define custom behavior we have two main points to introduce the desired logic. Editing the file contracts/custom_nft/src/entry.rs, we find two sections marked through code comments.
Composite script section: allows defining a list of basic behaviors that we want our NFT to implement. In this section, we can choose from the basic behaviors available in the extensions module.
Custom behavior section: this section allows defining custom behaviors through Rust code.
Once the behavior definition is completed we can build the typeScript using Capsule.
<pre><code>capsule build</code></pre>
The resulting script can be tested by a test included in the repository using capsule again.
<pre><code>capsule test</code></pre>
In order to use the script in production we must build it in release mode.
<pre><code>capsule build --release</code></pre>
A Javascript SDK to simplify integration into Dapps
Having defined a standard for NFTs allows creating pre-built tools to interact with them. The SDK developed by our team serves this purpose, it allows creating, reading, and managing factory Cells and NFTs in a simple way, so Dapps developers can adopt our standard without the need to get into the transaction implementation details. The source code along with examples of usage are available in Github.
Installing and setup
The SDK is available on npm package manager, it can be installed by running:
<pre><code>npm install @rather-labs/nrc-721-sdk</code></pre>
To run the examples available in the repository a testnet address and private key will be needed, they can be generated using this tool. We will also need some ckb to create the cells, on testnet we can get this ckb by inserting our address in this faucet.
The examples are set up to connect to a node and indexer running locally, a local testnet or dev node can be run following the instructions here, and here to run a local indexer. Nervos also maintains a public testnet node and indexer that can be used just by setting the URLs:
<pre><code>nodeUrl = "http://3.235.223.161:18114";
indexerUrl = "http://3.235.223.161:18116";</code></pre>
Minting a Factory Cell
To be able to create NFTs we first need to mint a factory cell, that will be used to mint NFTs from it and store common info, so it acts as a collection. Unless some custom functionality is needed, the factory can be created using the Type ID logic that is built into Nervos blockchain, so no contract deployment is needed.
The factory can be minted just by indicating the basic info it will contain:
<pre><code>const { rawTransaction, typeScript, usedCapacity } =
await factoryCell.mint({
name: "Test token factory",
symbol: "TTF",
baseTokenUri: "http://testtoken.com",
sourceAddress: OWNER_ADDRESS,
targetAddress: OWNER_ADDRESS,
fee: 0.0001,
});</code></pre>
the full example code can be found here. After minting our factory cell we will have its typeScript that will be used to identify our cell in the blockchain and will be needed to mint our NFTs.
Now we have our factory and from the previous section we should also have a deployed contract to govern our NFTs, so we are ready to mint our tokens, we just need the typeScript of our contract cell. We have also deployed our base NRC-721 contract in the testnet and is available to anyone to test the SDK integration, you can find its typeScript in our Github.
We are now ready to mint our NFTs using this example, indicating our contract and factory typeScripts. A data object can also be included, by default it will be serialized using JSON and stored in the data part of the NFT cell:
<pre><code>const { rawTransaction, nftTypeScript, usedCapacity } =
await nftCell.mint({
nftContractTypeScript,
factoryTypeScript,
sourceAddress: OWNER_ADDRESS,
targetAddress: OWNER_ADDRESS,
fee: 0.0001,
data: {
someKey: "SomeValue",
anotherKey: "AnotherValue",
},
});</code></pre>
The minted token can be retrieved from the blockchain using the SDK as shown in this example. We will be able to get all the info for the token and factory, so we can now use it on our Dapp:
<pre><code>Nft Token Id: d9ae00e88a7c2c701df1a7ee410b05a67c0a13fc50bfa0bbe05553d4ddb7e75eNft
Token URI:
http://testtoken.com/d9ae00e88a7c2c701df1a7ee410b05a67c0a13fc50bfa0bbe05553d4ddb7e75e
Nft Cell Data: { someKey: 'SomeValue', anotherKey: 'AnotherValue' }Factory Data: {
name: 'Test token factory',
symbol: 'TTF',
baseTokenUri: 'http://test-token.com'
}</code></pre>
Stay tuned for more articles regarding efficient scripting in Nervos Network.
Rather Labs, Inc. | Github | LinkedIn