Native Tokens

Native Tokens

Native Tokens

Native Tokens

This guide provides an overview of native tokens on Novo, detailing their implementation, usage, and integration into various transaction types

This guide provides an overview of native tokens on Novo, detailing their implementation, usage, and integration into various transaction types

This guide provides an overview of native tokens on Novo, detailing their implementation, usage, and integration into transaction types

This guide provides an overview of native tokens on Novo, detailing their implementation, usage, and integration into various transaction types

It outlines the benefits of native tokens for developers and users, including simplified smart contract development and reduced transaction fees. Also presented are examples for creating and managing fungible and non-fungible tokens, while explaining the underlying data structures and standards involved. By following along, you'll gain a solid understanding of how native tokens function within the Novo ecosystem, enabling you to utilize and build upon this powerful feature.

It outlines the benefits of native tokens for developers and users, including simplified smart contract development and reduced transaction fees. Also presented are examples for creating and managing fungible and non-fungible tokens, while explaining the underlying data structures and standards involved. By following along, you'll gain a solid understanding of how native tokens function within the Novo ecosystem, enabling you to utilize and build upon this powerful feature.

It outlines the benefits of native tokens for developers and users, including simplified smart contract development and reduced transaction fees. Also presented are examples for creating and managing fungible and non-fungible tokens, while explaining the underlying data structures and standards involved. By following along, you'll gain a solid understanding of how native tokens function within the Novo ecosystem, enabling you to utilize and build upon this powerful feature.

It outlines the benefits of native tokens for developers and users, including simplified smart contract development and reduced transaction fees. Also presented are examples for creating and managing fungible and non-fungible tokens, while explaining the underlying data structures and standards involved. By following along, you'll gain a solid understanding of how native tokens function within the Novo ecosystem, enabling you to utilize and build upon this powerful feature.

Introduction

Native tokens are a novel feature on Novo that facilitate multi-asset transactions. Users can transact with Novo and an unlimited number of user-defined (custom) tokens natively.


Offering native support provides distinct advantages for developers. There is no need to create smart contracts specifically for handling custom tokens. Instead, smart contracts can focus on executing business functions. This eliminates an extra layer of complexity and reduces the potential for manual errors, as the ledger manages all token-related operations. Additionally, transaction fees are lower when minting and utilizing tokens.


Custom-created native tokens represent a certain value and function as an accounting unit. They can be employed for payments, transactions, and integration with smart contracts.


To make tokens equivalent to Novo, the structure of UTXO is extended.


Each transaction output (TxOut) includes an optional contract section that records information pertinent to the native token. The fields are as follows:

ContractType (uint64, Defined with: FT, NFT, FT_MINT, NFT_MINT)

ContractID (txid+vout 36 bytes, the outpoint when the contract is published)

ContractValue (uint256, the value of FT, the tokenID of NFT, and the total issued amount of MINT.)

ContractMaxSupply (uint256, the FT/NFT maximum circulation)

ContractMetadata (string n bytes, any data less than 1KB, initialized once when created, and then read-only)

The recently incorporated token data is optional and maintains compatibility with the original structure. An output may contain either no tokens or only one type of token.


Once the contract is established, the ContractID, which is globally unique, serves to differentiate various tokens.


In the process of transferring tokens between addresses, transaction fees must be paid using Novo, and a minimum of 5 NOVO (dust limit) is required for the token output.

Usage

Example: Creating Your Own Fungible Token (FT)

Creating a fungible token with the node command tool is as straightforward as sending Novo to an address. Keep in mind that creating tokens necessitates Novo for transaction fees.


Initially, ensure that the wallet balance is sufficient. To create a total of 21,000,000 FT and designate it as TESTCOIN, execute the following command. The creator's address is miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6:

./novo-cli createtoken FT 21000000 '{"name":"TESTCOIN","symbol":"TC","decimal":8}' miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6

c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0

The token's unique identifier is c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0, which represents the ContractID.


When tokens are first created, they have no supply. Let's mint some – Here we mint 1,000,000 and 50 tokens into the address.

./novo-cli minttoken FT c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0 1000000 msfgzzQqGeQi2nakiiqh42MS1ueELzbyNx

./novo-cli minttoken FT c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0 50 miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6

Example: Transferring Tokens to Another User

To receive tokens, the recipient generates their wallet address by executing the command 'novo-cli getnewaddress' and shares it with the sender. The sender then proceeds by running:

./novo-cli transfertoken FT c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0 100 msfgzzQqGeQi2nakiiqh42MS1ueELzbyNx

Example: Creating a Non-Fungible Token (NFT)

By employing various types in the 'createtoken' command, we can generate NFTs. For instance, here we create an NFT with a total circulation of 100, designated as TESTCARD, with the creator's address miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6:

./novo-cli createtoken NFT 100 '{"name":"TESTCARD",description:""}' miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6

d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0

The token's unique identifier is d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0, representing the ContractID.


When non-fungible tokens are initially created, they have no supply. To mint them individually, we will add 3 tokens to the address, each with distinct metadata (D1/D2/D3):

./novo-cli minttoken NFT d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0 '{"name":"D1",description:""}' msfgzzQqGeQi2nakiiqh42MS1ueELzbyNx

./novo-cli minttoken NFT d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0 '{"name":"D2",description:""}' msfgzzQqGeQi2nakiiqh42MS1ueELzbyNx

./novo-cli minttoken NFT d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0 '{"name":"D3",description:""}' msfgzzQqGeQi2nakiiqh42MS1ueELzbyNx

The auto-incremented number is used as the tokenID for NFT minting.

Example: Transferring an NFT to Another User

To transfer a specific NFT, both the contractID and tokenID must be specified.


The recipient generates their wallet address by executing the command 'novo-cli getnewaddress' and shares it with the sender. The sender then proceeds by running:

./novo-cli transfertoken NFT d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0 1 n1RZhxvsNRVXFgB1GKbE9XtscYUKMMcSGx

Example: Viewing All Tokens You Own

After receiving the token, you can utilize the 'listcontractunspent' command to obtain the UTXO of all tokens.

./novo-cli listcontractunspent

[

{

"txid": "7e305ff908f3251967b5026ed38311bf513f86873368389f1f083dbfb0d8f601",

"vout": 0,

"address": "n1RZhxvsNRVXFgB1GKbE9XtscYUKMMcSGx",

"account": "",

"scriptPubKey": "76a914da5d94a04ada05253448c6cee108c67cfdc25d0588ac",

"amount": 0.4368,

"contractType": "NFT",

"contractID": "d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0",

"contractValue": "0",

"contractMaxSupply": "100",

"contractMetadata": '{"name":"D1",description:""}',

"confirmations": 63,

"spendable": true,

"solvable": true

},

{

"txid": "df8194645691a3d65613ed3b2cae8c9b8797121d53d384d2e0d65c8ca7c4f908",

"vout": 1,

"address": "miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6",

"account": "",

"scriptPubKey": "76a91421aab58a9e80ca6a7f28c5ebcbcc94286d410f6988ac",

"amount": 0.4368,

"contractType": "NFT_MINT",

"contractID": "d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0",

"contractValue": "3",

"contractMaxSupply": "100",

"contractMetadata": '{"name":"NFT_CARD",description:""}',

"confirmations": 63,

"spendable": true,

"solvable": true

},

{

"txid": "478ef48c0e753c2956c681c92a02ed101059b11044f59dbdf1254b3c84711e53",

"vout": 1,

"address": "miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6",

"account": "",

"scriptPubKey": "76a91421aab58a9e80ca6a7f28c5ebcbcc94286d410f6988ac",

"amount": 0.4368,

"contractType": "FT_MINT",

"contractID": "c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0",

"contractValue": "4300",

"contractMaxSupply": "21000000",

"contractMetadata": '{"name":"TESTCOIN","symbol":"TC","decimal":8}',

"confirmations": 63,

"spendable": true,

"solvable": true

},

{

"txid": "29506301f26f6fe593440d197e427d9212875c32203e3629e1235260f61c417b",

"vout": 1,

"address": "msfgzzQqGeQi2nakiiqh42MS1ueELzbyNx",

"account": "",

"scriptPubKey": "76a91485487c71ae9a6ab0652df0a95dfd681d6285236388ac",

"amount": 0.4368,

"contractType": "FT",

"contractID": "c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0",

"contractValue": "100",

"contractMaxSupply": "21000000",

"contractMetadata": '{"name":"TESTCOIN","symbol":"TC","decimal":8}',

"confirmations": 63,

"spendable": true,

"solvable": true

},

...

Furthermore, custom creation of 'rawtransactions' can be employed to accomplish these objectives. At this point, it is essential to understand the output structure of the native token.


  • 'createrawtransaction'

  • 'signrawtransaction'

  • 'sendrawtransaction'

  • 'decoderawtransaction'

Contracts

FT_MINT

When using the 'createtoken FT' command, a minting contract of the FT_MINT type is created. The FT_MINT contract can only be used for minting FTs and is not an FT itself. The contract rules are as follows:

ContractType:

It is set as FT_MINT and is immutable.

ContractID:

This is unique and immutable.

ContractValue:

This represents the amount of tokens minted, which increases as more tokens are issued.

ContractMaxSupply:

This refers to the maximum circulation and is immutable.

ContractMetadata:

This is the metadata, which is immutable. Please refer to the Token Standard.

FT

An output of the FT type indicates that an FT is attached to the output. When using the 'minttoken FT' command, the UTXO of FT_MINT will be spent, generating a new UTXO of FT_MINT and a UTXO of the newly minted FT. The contract rules for the FT are as follows:

ContractType:

It is set as FT and is immutable.

ContractID:

This is unique and immutable. It is inherited from FT_MINT and remains consistent with it.

ContractValue:

This represents the amount of this token, which changes when a transfer occurs.

ContractMaxSupply:

This refers to the maximum circulation and is immutable. It is inherited from FT_MINT and remains consistent with it.

ContractMetadata:

This is the metadata, which is immutable. It is inherited from FT_MINT and remains consistent with it.

NFT_MINT

When using the 'createToken NFT' command, a minting contract of the NFT_MINT type is created. The NFT_MINT contract can only be used for minting NFTs and is not an NFT itself. The contract rules are as follows:

ContractType:

It is set as NFT_MINT and is immutable.

ContractID:

This is unique and immutable.

ContractValue:

This represents the number of minted NFTs, which increases as more NFTs are issued.

ContractMaxSupply:

This refers to the maximum circulation and is immutable.

ContractMetadata:

This is the metadata of the series of NFTs and is optional. Please refer to the Token Standard.

NFT

An output of the NFT type indicates that an NFT is attached to the output. When using the 'minttoken' command, the UTXO of NFT_MINT will be spent, generating a new UTXO of NFT_MINT and a UTXO of the newly minted NFT. The contract rules for the NFT are as follows:

ContractType:

It is set as NFT and is immutable.

ContractID:

This is unique and immutable. It is inherited from NFT_MINT and remains consistent with it.

ContractValue:

This represents the tokenID of this NFT and is immutable. It starts from 1.

ContractMaxSupply:

This refers to the maximum circulation and is immutable. It is inherited from NFT_MINT and remains consistent with it.

ContractMetadata:

This is the metadata of this NFT. Please refer to the Token Standard.

Token Standard

Token Standards

Fungible Token (FT) Standard

It's recommended to use a serialized JSON with the following structure:

Field

Type

Description

name

string

Name of the Token

symbol

string

Symbol of the Token

decimal

number

Decimal of the Token

Example:

./novo-cli createtoken FT 21000000 '{"name":"TESTCOIN","symbol":"TC","decimal":8}' miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6

c841d5322f7553517e19e833420048bf55473be7faea7b54ce00ca1c8afcdc2a:0

Non-Fungible Token (NFT) Standard

It's recommended that the metadata for NFTs be either a URI (e.g., https://ipfs.io/ipfs/QmeSjSinHpPnmXmspMjwiXyN6zS4E9zccariGR3jxcaWtq/1) or a serialized JSON with the following structure:

Field

Type

Description

name

string

Name of the NFT

description

string

Description of the NFT

image

string

URI pointing to the NFT

Example:

./novo-cli minttoken NFT d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0 '{"name":"TESTCARD-01",description:""}' msfgzzQqGeQi2nakiiqh42MS1ueELzbyNx

NFT Collection Standard

When creating a collection of NFTs, a general message can be set to display the basic information. We recommend using a serialized JSON with the following structure:

Field

Type

Description

name

string

Name of the Collection

description

string

Description of the Collection

image

string

URI pointing to the Collection

Example:

./novo-cli createtoken NFT 100 '{"name":"TESTCARD",description:""}' miay6TrfZgGfbCuMrJtCmUe9sPCbFurng6

d6692f2b87c2aac24fd0f512aad1b92430ae33778f2c21b5505ac82246eceebd:0

Developer Guide

To support native tokens, developers should pay attention to the following points:

TxOutput

The transaction output structure has changed. A specific output now includes a native token, meaning that in addition to the value and script, there is also a token data segment within the output.

SignatureHash

During transaction serialization, the transaction output containing the native token will serialize the token data before serializing the value. When calculating the signed SignatureHash, if the spent UTXO contains the native token, the token data will also be added before the serialized value. Please refer to BIP143, where sections 6. value and 8. hashOutputs may be affected by the token data.

Subscribe to the Novo newsletter

Novo updates & news. No spam ever.

Copyright © 2023 Novo Community

Novo Icon

Subscribe to the Novo newsletter

Novo updates & news. No spam ever.

Copyright © 2023 Novo Community

Novo Icon