Skip to content
/ tnt Public

(T)ON (N)FT (T)ool - All-in-One command-line utility to query, modify, and mint new NFTs on TON blockchain

License

Notifications You must be signed in to change notification settings

TegroTON/tnt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

16 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

🧨 TNT

TNT is an all-in-one command line tool to query, edit, and mint new Non-Fungible Tokens on The Open Network. Written in Kotlin it enables fully cross-platform experience with no extra dependencies and does not rely on any third-party services. Out-of-the-box multiple network configurations are provided, for easy use in mainnet (live TON network) as well as testnet, and sandbox for experiments and development.

Disclaimer: TNT is software in early development, based on beta versions of underlying tools and libraries. Although possible, it is strongly discouraged to use its modifying capabilities (commands such as tnt mint) in live TON mainnet network, as it may result in loss of funds.

TNT is provided WITHOUT ANY WARRANTY

Installation

Currently, only JVM-based builds are available. Any JDK supporting Java 11+ is sufficient to run and use TNT.

  1. Download latest version from releases page. Development versions are built for each commit and can be found on the actions page.
  2. Extract downloaded archive
  3. Use ./bin/tnt to run commands.

Getting Started

TNT features multiple commands to query, modify, and create new NFT items and collections on The Open Network blockchain.

It is important to note use of --network=mainnet|testnet|sandbox option in following examples to explicitly specify target network, as attempting to call an operation on a contract residing in a different network will inevitably fail. This option defaults to testnet.

Getting NFT Collection Information

In order to get NFT collection info, such as number of items in it or its owner account, tnt collection command is used as follows:

$ tnt --network=mainnet collection 'EQAadrsHePbHk-v7KtM4_jrX0HTlMYfP9ZGtlLgn590D7-SC'
                    Collection Properties                     
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Address β”‚ EQAadrsHePbHk-v7KtM4_jrX0HTlMYfP9ZGtlLgn590D7-SC β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Size    β”‚ 7778                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Owner   β”‚ EQDVF5iErB47ryuH2HRBrbVIm-EKrb5WdTStrGEM8F9i77qB β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                            Collection Content                            
β”Œβ”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Kind β”‚ off-chain                                                       β”‚
β”œβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Uri  β”‚ https://s.getgems.io/nft/b/c/626a922e5e67c1f424154711/meta.json β”‚
β””β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Getting NFT Item Information

To get information about a particular NFT item, whether or not it belongs to any specific collection, use tnt item:

$ tnt --network=mainnet item 'EQA9V87ROI2DZqm65Jj-CIaOMF4RgElzOge0YgktWqyOJO1x' 
                         Item Properties                          
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Address     β”‚ EQA9V87ROI2DZqm65Jj-CIaOMF4RgElzOge0YgktWqyOJO1x β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Initialized β”‚ true                                             β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Index       β”‚ 69                                               β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Collection  β”‚ EQAadrsHePbHk-v7KtM4_jrX0HTlMYfP9ZGtlLgn590D7-SC β”‚
β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Owner       β”‚ EQChmtQM0oJX01hIY-9ej_whDeAWqtz_UtqlnDJJBpUszX28 β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                           Item Content                           
β”Œβ”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Kind β”‚ off-chain                                                          β”‚
β”œβ”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
β”‚ Uri  β”‚ https://s.getgems.io/nft/b/c/626a922e5e67c1f424154711/69/meta.json β”‚
β””β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Minting items and collections

Note: This is a modifying operation, that will send actual transactions to the chosen network. Certain amount of toncoins is required to perform these operations, it is strongly recommended to use free test coins provided by faucet bots in testnet or sandbox.

Unlike other tools used for mint of NFT items and collections, TNT deploys a single-use wallet contract for each invocation of tnt mint command. Main reason for this is security, as it eliminates the need of passing around secret keys or mnemonic seed phrases. Whenever an NFT entity is deployed, ownership is then transferred to an actual owner account, that is assumed to have its secrets stored in a secure place. Another big reason is the ability to use more efficient contracts for deployment, such as high-load wallets, speeding up deployment of large collections. Importantly for testing, it also means that mint of the same entity multiple times will result in a new address being generated each time.

On the other hand, because a new account is used each time, insufficient balance or any failure during TNT's run may result in funds being permanently locked in an inaccessible contract. Failure recovery functionality is planned to be implemented in the future, when this tool reaches its first stable release.

It is also important to note that at the moment there is no way to estimate processing fees required to run smart-contracts on TON, and because of this it is up to the user to provide sufficient amount of funds for this tool to operate. Approximate amounts are currently specified as constants, and can be modified by the user. As a general rule of thumb, minting a single item, whether standalone or in collection, will cost about ~0.3 TON. This amount includes worst case scenario blockchain fees and was choosen to be a safe default, in reality it costs less than 0.2 TON.

Specification file

For better portability, TNT reads desired item/collection properties from a specification JSON file. This means that the same collection may be deployed in testing network during development, and then simply minted according to the same specification in mainnet.

Please note, before TNT reaches stable version, specification format is a subject to change. Original files of the following examples can be found in the examples directory.

Standalone item example specification

Here's an example of a specification, that will mint a standalone (meaning it does not belong to any collection) item when passed to tnt mint

{
  "entities": [
    {
      "type": "item",
      "index": 69,
      "owner": "EQDpl_EDsAwIME91TvXCi6xsM_7dYaB4vZoDbcu_QHmldeUI",
      "content": {
        "type": "full_snake",
        "value": "https://s.getgems.io/nft/b/c/626a922e5e67c1f424154711/69/meta.json"
      }
    }
  ]
}

entities - an array of NFT entities (standalone items/collections) to mint. Single specification may contain multiple entities of any kind.

type - must be "item" for standalone items.

index - index of an item in the collection. Makes no difference for standalone items, and it is recommended to set it to "0" in this case.

owner - contract to be assigned as the owner of this item. After successful mint a transaction will be sent to this address. Base64(url) and raw addresses are supported, with special value "none" indicating empty owner. This will essentially "burn" this item, as it will not be possible to ever change its owner again.

content - item content, its metadata. In this case it is a "full_snake" content kind, meaning it is a string containing a URL to off-chain JSON file that is encoded in "snake data" format.

For more advanced users, "cell" kind of data may be used, where value is's a base64-encoded Bag-of-Cells with a single root cell that will be used as item's content.

{
  "type": "cell",
  "value": "base64-encoded BoC with a single root cell"
}

To mint this standalone item, use the following command:

$ tnt --network=testnet mint examples/lonely_dog.json

And proceed with the instructions. You will have to send at least 0.3 TON to the newly generated wallet address in testnet.

Collection of items

For this, a slightly different specification is used:

{
  "entities": [
    {
      "type": "collection",
      "collection_content": {
        "type": "full_snake",
        "value": "https://s.getgems.io/nft/b/c/626a922e5e67c1f424154711/meta.json"
      },
      "common_content": {
        "type": "naked_snake",
        "value": "https://s.getgems.io/nft/b/c/626a922e5e67c1f424154711/"
      },
      "owner": "EQDpl_EDsAwIME91TvXCi6xsM_7dYaB4vZoDbcu_QHmldeUI",
      "royalty": {
        "numerator": 69,
        "denominator": 1000,
        "destination": "EQDpl_EDsAwIME91TvXCi6xsM_7dYaB4vZoDbcu_QHmldeUI"
      },
      "items": [
        {
          "owner": "EQDpl_EDsAwIME91TvXCi6xsM_7dYaB4vZoDbcu_QHmldeUI",
          "content": {
            "type": "naked_snake",
            "value": "1/meta.json"
          }
        }
        ...
      ]
    }
  ]
}

entities - same as before, single specification may contain multiple items and collections to mint.

type - must be "collection"

collection_content - metadata of this particular collection contract. Note the use of "full_snake" kind, it is important as wrong encoding may result in client applications not being able to read collection content properly.

common_content - part of metadata that is common between all items of this collection. Usually this is the longest common part of URL to item metadata. Note the use of "naked_snake" kind, it is important because collection smart contract concatenates common content, with individual item content via its get method, producing valid "full_snake" snake data for the clients.

owner - an address of account that will be able to modify collection metadata as well as mint more items.

royalty - this section contains information about royalties from each sale of any item in the collection.

royalty.numerator, royalty.denominator - these two properties specify percentage that will be sent to royalty holder on a sale. Maximum is 15% Percentage is computed as numerator/denominator, in this case it is 6.9%.

royalty.destination - address of an account that will receive the royalty. It is possible to set it to "none", as well as setting numerator and denominator to 0, which will essentially disable royalty functionality of the smart-contract.

items - an array of every item in the collection, specifying item's owner and content. Note that item order matters, first item is assigned index of 0, next has index of 1, and so on. TNT always obeys the original order of items.

In order to mint this collection, use the following command:

$ tnt --network=testnet mint examples/tegro_dog.json

Proceed according to instructions, you will have to send at least 3 TON to the newly generated single-use address in testnet.

Reporting Issues

Please, use issues page to report any bugs, ask questions or suggest new features.

When reporting bus, make sure to provide as much helpful information as you can: operating system and its version, JDK version used to run TNT, exact command line you used and program's output you got.

TNT also creates log files for each invocation in system's temporary path, which is usually /tmp on Unix-like systems and %TEMP% on Windows. Files are named as tnt.<yyyyMMdd'T'HHmmss>.log, middle part being the exact time of program startup. These log files are immensely helpful when troubleshooting.

Warning: When running tnt mint, log files contain single-use wallet's private key. This is done intentionally to allow recovery of coins in case of failure, but may pose a security risk if misused. Never share these raw log files without first removing sensitive information from them.

In future versions, this behaviour will be changed.

About

(T)ON (N)FT (T)ool - All-in-One command-line utility to query, modify, and mint new NFTs on TON blockchain

Topics

Resources

License

Security policy

Stars

Watchers

Forks

Contributors 3

  •  
  •  
  •  

Languages