TON is not a new Layer 1 Blockchain by any means, but it has seen exponential growth in the first half of this year. Daily transactions are climbing upwards of 5+ million per day with no signs of stopping anytime soon.
If you’re not familiar with TON, it’s a proof of stake network that is heavily integrated with Telegram; most of the people building Telegram are also building TON. This level of integration poses a unique approach to consumer crypto by tapping into a well used social platform in Web3, allowing wallets, dApps, and more without leaving Telegram. Not only that, but TON also has an interesting multi-chain approach, where there is a master chain that handles critical information and then uses work-chains for different transactions. This model enables high performance and low fees. If you’re a developer looking to start building on TON, there’s no better way to start than to mint an NFT! In this guide, we’ll show you how to do just that by building an app that uploads the NFT assets securely to Pinata and mints an NFT on TON.
TON vs Ethereum NFTs
Before we dive into the main tutorial, it might help to explain how TON differs from Ethereum when it comes to NFTs. With Ethereum, or other EVM chains, you typically have a single smart contract with many NFTs. This has proven to cause unpredictable gas prices which trickle down to the end user. TON NFTs, on the other hand, have a contract for each NFT that are linked to a collection contract, which results in a more stable model for minting.
Since TON takes this approach, the developer tooling also looks very different. Instead of writing a smart contract that imports OpenZeppelin standards, deploying, testing, etc., we can just use TON’s libraries to create the collection on the fly. All we have to do is pass in the right metadata, then make additional calls to the master collection for each NFT we mint. That’s exactly what we’ll do in our app!
Setup
In order to start building the TON app we’re gonna need a few things first.
Pinata Account & API Key
Like with most other blockchains, we need a way to store the token URI of our NFTs offchain, and IPFS fits the bill. To use IPFS, we’ll need to make a free Pinata account here. Once we’ve created the account, we’ll want to make an API key that we can use to upload content from our TON app. You can do so by following these instructions, ensuring careful attention to copy down the API key somewhere safe. We’ll be using the longer JWT in particular.
Telegram
Since TON is so heavily integrated with Telegram I would recommend making an account, if you haven’t already, as well as downloading the desktop client as we build through the app. There will be several setup points that require interacting with bots through Telegram, and it’s probably the easiest way to walk through those parts.
TON Wallet
The next thing you’re gonna need is a TON wallet, as an EVM wallet like MetaMask isn’t going to work here. For this tutorial, we’ll use the official TON Wallet extension, as our code will be able to plug right into it. Once you’ve created the wallet and followed the steps to secure it, we’ll need to put it into testnet mode. To do this, you’ll want to click on the three dots in the top right, then shift+click on the version listed. This will trigger a modal for switching to testnet.
Now that we’re in testnet mode, we need to get testnet funds! You can do this by following this link which will open a new chat in Telegram with the faucet bot. Just follow the steps, provide your wallet address, and you’ll get some testnet funds!
TON API Key
Our app is going to use some of the TON libraries, which will send requests to an RPC node on toncenter.com and, because of that, we’ll need an API key to access it. You can get one by following this link which will, again, open a new Telegram chat with a bot that can give you the API key.
Next.js
Just for simplicity, we’ll be using Next.js as our stack, as we need a way to secure our Pinata API key. To kick off, run the following command in the terminal and select all the defaults.
npx create-next-app@latest ton-minting-tutorial
Once it’s done installing dependencies, run the following command to move into the project and install the TON library.
cd ton-minting-tutorial && npm install tonweb uuid
Now we can start building this thing out!
Building the App
As stated, we’ll be building an app that does the following:
Lets users connect their wallet
Create an NFT collection
Mint an NFT in the collection
Pretty simple! To start, let’s handle our API keys by creating an .env.local file and fill in the variables below:
PINATA_JWT= // Pinata JWT from when we made our API key earlier
NEXT_PUBLIC_TON_API_KEY= // TON API key we made through the bot
After we have those keys in place, you will want to make a new file in the root of the project called constants.config.ts and put in the following code.
One other small thing we will need to do is make a custom type exception for window.ton, just like we do for Ethereum. Make a file called new-types.d.ts in the root of your project and put in the following contents.
To make sure the new types are included in our project build settings you will want to add the filename to the array in tsconfig.json
Now, we can navigate to our main app page app/page.tsx, clear out the boiler plate, and import some dependencies.
To start using the TonWeb library, we’ll import a constants, as well as create a new TonWeb instance.
With that completed, we can create a function that allows users to connect their wallet with us by adding the following code:
In this code, we do something similar to Ethereum where we get the window.ton object, check if there is a wallet connected and, if not, prompt the user to connect. Once they connect, we set the account to our useState for later. If the user doesn’t have a wallet, or if it’s outdated, we can give them a link to the extension.
Once we have their wallet connected, we can start looking into creating the NFT collection. In order for this to work on TON, we actually need contract metadata, just like we do for individual NFTs, otherwise we won’t really see much on marketplaces or explorers. Thankfully, we can just as easily store this on IPFS as we can with the NFT itself! To handle uploads in a secure fashion, we’re going to take a “signed JWT” approach where we use a Next.js API route to generate temporary keys that we can use for uploads on the client side.
To make this little API, we’ll make a route in our files with the path app/api/key/route.ts . Inside that route.ts file, we want to go ahead and put in the following code.
With this method, we can create a temporary key that can only be used once and is limited to just pinFileToIPFS and pinJSONToIPFS. Now that we have our API endpoint ready, we can make the upload functions to handle files - like images and JSON data - for NFT metadata! Make a new folder in the root of your project called utils/uploads.ts and put in the following code.
These two functions are pretty straight forward. For each one, we request a temporary key, then used it in our upload. uploadFile takes a file like an image and uploadJson takes any kind of object - both return a CID we can use for the NFTs.
With the upload step complete, we can now create our other two TON functions in app/page.tsx. Like we mentioned earlier, we need the user to create a collection first, and once it’s deployed, we can mint NFTs to that collection. The collection metadata has several requirements such as a name, description, external link, image, and royalty points. Let’s add that code now to page.tsx.
At the top of the file, we import our upload functions and declare some new states. In our deployCollection function, we’ll first connect to the TON provider, then we’ll upload the image provided for the collection. With that CID, we’ll construct the metadata object for the collection, which takes in most of the parameters we’ll ask for in the front end. One nice thing to note is that we can use the ipfs:// protocol url, as TON made the effort to support it in their ecosystem to help ensure persistent content, which you can read more about here.
Once we have our collectionData ready we can upload it with uploadJson, which will give us a CID that will act as the collectionUri. Now, we can actually create the collection using new NftCollection from the TON library, where it is then passed through a state initialization, BOC (Bags of Cells) binary object, base6, which is finally passed into provider.send where we send the BOC data and prompt the user to sign the transaction. If all goes well, then we can set the nftCollectionAddress and nftCollection object for minting the NFT.
Minting the NFT to the collection looks pretty similar. Let’s update our page.tsx file.
In this function, we follow the same pattern where we upload an image, use the image CID in the metadata, upload the metadata, which then leaves us with a nftUri. We can use the nftCollection object we made earlier to pass in that nftUri the same way we did before with the IPFS protocol url: ipfs://. Additionally, we can pass in things like the itemIndex which works like a token ID. Generally, you would want to use TonWeb to fetch the latest index and increment it, since it doesn’t happen automatically like most Solidity smart contracts. After we have our body complete, we can compile it to BOC, the bytes to base64, and finally send the transaction to the collectionAddress.
With all of our functions ready to go, we can add in our JSX forms and fields.
There’s a lot here, so let’s break it down a bit. In the beginning, we check if there is a connected address and, if not, show the button for the user to connect with. Then, we show the “create collection” section of our app. Once the collection is deployed, we show the mint section. Both of these sections use the state we declared earlier to fill in the fields of our collection and NFT metadata. Once the user has minted the NFT, we can show them a completion modal where they can view the NFT on getgems.io!
To see the full code for this tutorial you can check out the repo here!
Wrapping Up
While TON is a shift from what most Web3 developers are used to, there is a plethora of material to learn from and build whatever you want! Having a blockchain built alongside a social platform is truly powerful. Building on it means having a whole different layer of distribution, and Pinata is here to help you scale and keep your content persistent.
Happy Pinning!
Share this post:
Stay up to date
Join our newsletter for the latest stories & product updates from
the Pinata community.
Error submitting email.
Success! Please confirm your email within 24 hours.