Get Started with TON
Set up your first application on TON Blockchain from scratch and discover its speed, reliability and essential concepts of asynchronous way of thinking.
If you are completely new with programming, this guide is the best choice for you.
This learning path contains 5 modules and should take you around 45 minutes.
🛳 What you will learn
In this tutorial, you'll learn how to easily make blockchain transactions using JavaScript. You could learn to do it without this tutorial, but this approach is convenient and user-friendly.
- You will make your own TON Wallet with Tonkeeper
- You will use a Testnet faucet to topup your wallet for testing
- You will understand essential concepts of TON smart contracts (Addresses, Cells)
- You will learn how to interact with TON using TypeScript SDK and API provider
- You will compile your first transaction using NFT Miner console application
You're going to mine an NFT rocket achievement!!!
As the first miners on TON, you will go through the Proof-of-Work smart contract and finally mine a secret reward for your TON wallet. Check it out:
Our goal for today is to mine an NFT! This achievement will stay with you forever.
Finally, you are able to mine this NFT achievement even in mainnet. (it costs only 0,05 TON!)
Video tutorial
Check out this awesome video tutorial created by a member of TON developer community! With this helpful guide, you can complete the tutorial with ease:
Mining on TON Blockchain
Today, we are going to teach our prospective builders how to mine on TON Blockchain. This experience will allow all of you to understand the significance of mining and why Bitcoin mining helped revolutionize the industry.
Though the PoW Giver smart contract framework that defined the initial mining process that helped lay the foundation for TON was completed at launch, the last TON was mined in June of 2022 to culminate TON’s Proof of Work (PoW) token distribution mechanism. That said, with our recent transition to Proof of Stake (PoS), the era of staking on TON has just begun.
Now, let’s focus on the first steps to becoming a TVM Developer and learn how to mine an NFT on TON! Provided below is an example of what we're aiming to create.
It’s possible to create a miner in about half an hour if we keep focused on the task at hand.
🦄 Getting started
To get started, all developers will make use of the following components:
- Wallet: You need a non-custodial wallet to store an NFT in testnet mode.
- Repository: We’ll use a ready-made template designed specifically for you.
- Developer Environment: Developers will need to determine whether they want to mine using a local or cloud environment.
Download and Create a Wallet
To start off, you’ll need a non-custodial wallet that will allow you to receive and store your TON; for this purpose in this guide we are using Tonkeeper. You’ll need to enable Testnet mode within the wallet to be able to receive Testnet Toncoins. These tokens will be used later on to send a final minting transaction to the smart contract.
With a non-custodial wallet, the user owns the wallet and holds its private key by themselves.
To download and create a TON wallet follow these simple steps:
- Install the Tonkeeper app on your smartphone. It can be downloaded here.
- Next, you’ll need to enable test mode within Tonkeeper.
Easy! Let's go to the development now.
Project setup
To make your life easier and skip routine low-level stuff, we will use a boilerplate.
Note, you'll need to sign in to GitHub for further work.
Please, use the ton-onboarding-challenge template to create your project by clicking on the “Use this template” button and selecting the “Create a new repository” tab as shown below:
After completing this step, you’ll have access to a highly performant repository that can be used as your miner's core. Congratulations! ✨
Development Environments
The next step is to choose which developer environment is best suited to your needs, experience level, and overall skill-set. As you can see, it is possible to carry out this process by using either a cloud-based or local environment. Developing on the cloud is often considered simpler and easier to get started. Below, we’ll outline the steps required for both approaches.
Make sure you have opened the repository in your GitHub profile that was generated from the template in the previous step.
Local and Cloud Development Environments
For users who are not familiar with JavaScript, it can be challenging to use a JavaScript IDE, especially if your computer and tooling systems are not configured for this purpose.
However, if you're familiar with NodeJS and Git and know how to work with
npm
, it may be more comfortable for you to use a local environment.
Cloud Codespaces
If you choose the cloud development environment it's easy to get started by first selecting the Code tab and then by clicking on the Create codespace on master button within the GitHub repository like shown below:
After completing this step, GitHub will create a special cloud workspace that allows you to access the VSCode Online IDE (Visual Code Online Integrated Development Environment).
Once access is granted (the codespace typically starts in about 30 seconds), you'll have everything required to begin without the need to install Git, Node.js, or other developer tools.
Local Development Environments
To set up a local development environment, you'll require access to these three essential tools:
- Git: Git is an essential tool that every developer needs to work with repositories. It can be downloaded here.
- NodeJS: Node.js is the JavaScript and TypeScript runtime environment typically used for application development on TON. It can be downloaded here.
- JavaScript IDE. JavaScript IDE’s are typically used for development within local development environments. An example of this case is Visual Studio Code (VSCode).
To get started, you’ll need to clone your GitHub repository boilerplate and open the correct repository in your Integrated Development Environment (IDE).
Running Scripts
In this guide, you'll need to run TypeScript scripts. All commands, such as running scripts or installing modules, are executed through the command line, which is located in the IDE's Terminal workspace. This workspace is typically found at the bottom of the IDE.
For example, in the Cloud Codespaces, you should open the Terminal workspace (if it is not already open):
Enter commands in this window and execute them with Enter:
The Terminal is also available as a separate application. Please choose the appropriate version based on your IDE and OS.
Great! After these steps you're ready to get deeper into TON Blockchain secrets. 👀
🎯 Connect to TON
Okay, what do you need to connect to TON Blockchain?
- Smart contract address as a point of destination. Our goal is to mine an NFT from the proof-of-work smart contract, so we need an address to get current mining complexity.
- API provider to make requests to TON Blockchain. TON has multiple API types for different purposes. We will use the testnet version of toncenter.com API.
- JavaScript SDK: A JavaScript SDK (recall that an SDK is a Software Development Kit) is needed to parse the smart contract address being used and prepare it to create an API request. To better understand TON addresses and why they need to be parsed to carry out this process, please see this resource to understand why should we parse it. To carry out this procedure, we'll use ton.js.
In the next section we’ll describe how users send their initial requests to TON Blockchain using the TONCenter API and ton.js to receive data from the PoW smart contract.
Smart Contract Addresses
For the miner to work correctly, we need to add two different smart contract address types. These include:
- Wallet address: A wallet address is required, because it is necessary for the miner to receive their mining reward (in this case, we must use the Tonkeeper Testnet mode).
- Collection address: A collection address is required to act as a smart contract to correctly mine an NFT (to carry out this process copy the NFT collection address, under the TON onboarding challenge collection name from the Getgems website).
Next, we’ll open the index.ts
file in your miner and create a main function composed of initial constants as follows:
import {Address} from "ton"
async function main () {
const wallet = Address.parse('YOUR_WALLET_ADDRESS');
const collection = Address.parse('COLLECTION_ADDRESS');
}
main()
Using the async main() Function
Later in the process of creating a TON NFT Miner, several requests will be executed to the public API to relay responses to the correct string of code in exchange for the desired instructions. By leveraging the Async/await function, code simplicity is improved dramatically.
Address Parsing
On TON, smart contract addresses come in different forms that employ the use of numerous flag types. In this context specifically, we’ll make use of the user-friendly address form. That said, if you are curious to learn more about the different smart contract address types, feel free to check out this additional resource in our documentation.
For the miner to work correctly, we need to add two different smart contract address types. These include:
The Address.parse()
command found in the ton.js
SDK allows the developer to create an address object to convert addresses from one form to another in a simplified manner.
Connect to an API Provider
In this step, we'll connect with TON via TONCenter (which is hosted on toncenter.com) API provider using specific commands in the script.
The simplest way to learn how it works is by using @orbs-network/ton-access.
Remember, if you are adding new modules with import
, that you may need to install them by executing the command npm i @orbs-network/ton-access
in the terminal.
We are adding client
and endpoint
in the index.ts
script using TonClient and getHttpEndpoint from @orbs-network/ton-access
:
import {Address, TonClient} from "ton"
import {getHttpEndpoint} from "@orbs-network/ton-access";
// ... previous code
// get the decentralized RPC endpoint in Testnet
const endpoint = await getHttpEndpoint({
network: "testnet",
});
// initialize ton library
const client = new TonClient({ endpoint });
It's better to use an RPC node provider, or to run your own ton-http-api instance for that. Read more at the TonCenter API page.
Receiving Mining Data From TON Blockchain
Finally, the next step in the process is to retrieve specific mining data from TON Blockchain.
By consulting the README file needed to complete the ton-onboarding-challenge, the latest TON mining data is obtained by running the get_mining_data
method. Once initiated, the result will be as follows:
As a result we should receive an array with these fields:
(
int pow_complexity,
int last_success,
int seed,
int target_delta,
int min_cpl,
int max_cpl
)
Running Smart Contract Get Methods on TON
Using ton.js
it is possible to run the callGetMethod (SMART_CONTRACT_ADDRESS, METHOD) function.
Running this code will result in the following console output:
// ... previous code
const miningData = await client.callGetMethod(collection, 'get_mining_data')
console.log(miningData)
Furthermore, to run the script, it is necessary to enter the following command in the terminal:
npm run start
To avoid unexpected issues, make sure you have finalized all previous steps, including inputting contract addresses.
Good! As long as the above processes were executed correctly, successful connection to the API will be achieved and the necessary data will be displayed in the console. The correct console output should be initiated as follows:
{
gas_used: 2374,
stack: [
[
'num',
'0x2880000000000000000000000000000000000000000000000000000000000'
],
[ 'num', '0x63984815' ],
[ 'num', '0x357401cf9b4f2386950faefd6b616264' ],
[ 'num', '0x1e' ],
[ 'num', '0xab' ],
[ 'num', '0xfc' ]
]
}
Above it displays the gas amount used to execute the process, as well as the sum of numerical (num) values in hex format. At this time, this data is not too critical because it is necessary to convert the hex output data into something that can be used more easily.
We need to convert the hex output to something useful.
Warning: Though this information is highly complex and not necessary for this tutorial, if you’re interested in understanding the complex technical aspects of TON consider using these resources:
- To obtain a better understanding of how TON Virtual Machine (TVM) operates and how does TON process transactions, check out TVM overview section.
- Secondly, if you are interested in learning more about how transaction and gas fees work on TON, consider diving into this section of our documentation.
- Finally, to get a better understanding of the exact gas values needed to carry out TVM instructions see this section of our documentation.
Now, let's return to the tutorial!
Numerical Mining Data in a User-Friendly Format
In the section above where we discuss gas amounts and numerical (num) values in hex format needed to receive mining data, we note that the hex numbers present within the strings of code must be converted into a more easily understandable and usable format.
As it is clear when examining the given output, hex numbers can be quite substantial in size. It's not possible to make a variable and make use of them, because of specific JavaScript limitations that are outlined here.
We need a way to translate this, that’s where the bn.js
(the big number implementation in JavaScript) library comes in. Bn.js is a library developers use to work with large numbers that are larger than the maximum JavaScript integer values. Let’s use this example to get a better idea of the Mining Data required for this process:
import {BN} from 'bn.js'
// ... previous code
const parseStackNum = (sn: any) => new BN(sn[1].substring(2), 'hex');
const complexity = parseStackNum(miningData.stack[0]);
const last_success = parseStackNum(miningData.stack[1]);
const seed = parseStackNum(miningData.stack[2]);
const target_delta = parseStackNum(miningData.stack[3]);
const min_cpl = parseStackNum(miningData.stack[4]);
const max_cpl = parseStackNum(miningData.stack[5]);
console.log('complexity', complexity);
console.log('last_success', last_success.toString());
console.log('seed', seed);
console.log('target_delta', target_delta.toString());
console.log('min_cpl', min_cpl.toString());
console.log('max_cpl', max_cpl.toString());
As shown above, the different components of miningData use a stack-based array with hex numbers for different parameters (which will be introduced in the section below). To achieve the desired value outcome, we added the parseStackNum function to create a BN (Big Number) object from a hex number.
After this process is complete, it is necessary to print values within the console. In this case, some values are printed as BN objects, which will make the process more user-friendly. Try to run the script again by running the command:
npm run start
Here is an example output:
complexity <BN: 2880000000000000000000000000000000000000000000000000000000000>
last_success 1670924309
seed <BN: 357401cf9b4f2386950faefd6b616264>
target_delta 30
min_cpl 171
max_cpl 252
Let's cover the Mining Data command that is used to translate different data parameters when programming mining data into TON Blockchain. These include:
complexity
is the most important number for miners. It's a Proof-of-Work complexity for the values. You're successful if the final hash is less than complexity.last_success
is a unix timestamp date and time representation that keeps track of the last mining transaction on TON. Each time the last_success metric changes, it's necessary to run the miner again because the seed also changes during this process.seed
denotes a unique value generated by a smart contract to calculate the desired hash. To better understand this process and learn more about how the seed changes and why, have a look at the project files folder by using the ctx_seed keyword(Ctrl+F with keyword "ctx_seed").target_delta
,min_cpl
andmax_cpl
won't be used in our tutorial. But you can always read more about how they are used in smart contracts to calculate proof-of-work complexity in the source files of the collection in your project.
Now that we understand the different parameters discussed above, we have the values(complexity
, last_success
, seed
) which we will use in our NFT Miner in the next chapter.
🛠 Prepare a NFT Miner
Hey, you're doing a great job!
After connecting to TON and retrieving the necessary mining data from the blockchain to create an NFT Miner, let’s focus on the next steps in this process to achieve our goal.
In this chapter you will prepare a mining message and calculate a hash of the message. After that, you will find a hash that's less(<
) than the complexity we got from the smart contract.
That is what a miner is! Simple, isn't it?
Preparing Mining Messages
First, we must prepare a mining message by ensuring the correct parameters to ensure the validity and data integrity of this process.
Thankfully, the README file allows us to retrieve the correct guidelines needed to achieve this goal. As you can see, the above README file comprises a table with certain fields and Cell types (titled “Layout of Proof of Work Cell’) to help achieve our desired result.
Cells are data storage structures on TON that fulfill numerous purposes, including increasing network scalable and smart contract transaction speeds. We won’t get into specifics here, but if you’re interested in understanding the complexity of cells and how they work, consider diving into this section of our documentation.
Fortunately, all the data structures used in this tutorial are already written in TypeScript. Use the MineMessageParams
object from NftGiver.data.ts to build a transaction with Queries:
import {unixNow} from "./src/lib/utils";
import {MineMessageParams, Queries} from "./src/giver/NftGiver.data";
// ... previous code
const mineParams : MineMessageParams = {
expire: unixNow() + 300, // 5 min is enough to make a transaction
mintTo: wallet, // your wallet
data1: new BN(0), // temp variable to increment in the miner
seed // unique seed from get_mining_data
};
let msg = Queries.mine(mineParams); // transaction builder
Probably, you have a question: where are the op and data2 from the table?
- In the table, the numerical value of data1 must be equal to that of data2. In order to omit filling the data2 value, the transaction builder performs a low-level process (see Queries.mine() sources).
- Because the
op
classification is always constant, it is already implemented in transaction builder Queries and in OperationCodes. You can find the op code by going to the source code ofmine()
method.
Though it may be interesting to check out the source code (./src/giver/NftGiver.data
), it is not necessary.
Creating TON NFT Miners
Now that we have completed the process to prepare messages for our TON miner, let’s jump into the initial process to actually create a miner. First, let’s consider this line of code:
let msg = Queries.mine(mineParams);
Above we compiled a msg
value. The idea of mining is to find a hash msg.hash()
that will be less than complexity
from the last received get_mining_data(). We can increment data1
as many times as we need.
The pure miner will continue to run indefinitely, as long as msg.hash()
is bigger than complexity
(message hash is larger than PoW mining complexity).
Here is an example of the code running as it relates to BigNumbers in TypeScript:
let msg = Queries.mine(mineParams);
while (new BN(msg.hash(), 'be').gt(complexity)) {
mineParams.expire = unixNow() + 300
mineParams.data1.iaddn(1)
msg = Queries.mine(mineParams)
}
console.log('Yoo-hoo, you found something!')
A few important considerations regarding Big Number (BN) functions:
- We create a big-endian BN object from the
msg.hash()
with'be'
attribute. gt()
: denotes greater than a variable for comparing BigNumbers.iaddn(1)
: denotes an incremented value.
Though the miner will work properly after the completion of the above steps, it will have a visually unappealing appearance (try npm run start
). Therefore, we must address this issue. Let’s jump in.
Improving TON Miner Appearance ✨
We want to make the miner look sexy now! How do we do it?
Just follow me, my friend, follow me.
To achieve our goal, we’ll add these commands:
let msg = Queries.mine(mineParams);
let progress = 0;
while (new BN(msg.hash(), 'be').gt(complexity)) {
progress += 1
console.clear()
console.log(`Mining started: please, wait for 30-60 seconds to mine your NFT!`)
console.log(' ')
console.log(`⛏ Mined ${progress} hashes! Last: `, new BN(msg.hash(), 'be').toString())
mineParams.expire = unixNow() + 300
mineParams.data1.iaddn(1)
msg = Queries.mine(mineParams)
}
console.log(' ')
console.log('💎 Mission completed: msg_hash less than pow_complexity found!');
console.log(' ')
console.log('msg_hash: ', new BN(msg.hash(), 'be').toString())
console.log('pow_complexity: ', complexity.toString())
console.log('msg_hash < pow_complexity: ', new BN(msg.hash(), 'be').lt(complexity))
Just check it out! Let’s execute the command:
npm run start
Cool, isn't it? 😏
After these commands are executed correctly, we’ll have a visually appealing NFT miner. In the next section, we’ll focus on connecting a wallet to the miner to create a payment channel that can accept and receive transactions from TON Blockchain.
🎨 Prepare a Transaction
Next, we’ll outline the steps to compile a message and send it to the blockchain with your Tonkeeper wallet. The upcoming steps will guide you in completing the process of mining an NFT on TON.
Creating a Payment Link
In order to ensure that the NFT mining process is carried out correctly, and that the user can store their NFT properly, we must create a payment link that is able to simultaneously interact with TON Blockchain and the Tonkeeper wallet.
To achieve this goal, we’ll initiate the creation of a payment URL (a payment link) using the ton://transfer/<address>
format that can be customized using different parameters. This will work perfectly because we want to create a message, and send it to the smart contract using our Tonkeeper wallet:
import {toNano} from "ton"
// ... previous code
console.log(' ');
console.log("💣 WARNING! As soon as you find the hash, you should quickly send the transaction.");
console.log("If someone else sends a transaction before you, the seed changes, and you'll have to find the hash again!");
console.log(' ');
// flags work only in user-friendly address form
const collectionAddr = collection.toFriendly({
urlSafe: true,
bounceable: true,
})
// we must convert TON to nanoTON
const amountToSend = toNano('0.05').toString()
// BOC means Bag Of Cells here
const preparedBodyCell = msg.toBoc().toString('base64url')
// final method to build a payment URL
const tonDeepLink = (address: string, amount: string, body: string) => {
return `ton://transfer/${address}?amount=${amount}&bin=${body}`;
};
const link = tonDeepLink(collectionAddr, amountToSend, preparedBodyCell);
console.log('🚀 Link to receive an NFT:')
console.log(link);
Let’s run the above script to launch the newly created payment link. Now it’s time to make the payment link running on your PC smartphone compatible. Let’s get started.
Creating A Smartphone Compatible Payment Link
As a solution, the most brilliant minds in the world created a QR code generator specifically for use in terminal. With this tool, you can simply scan the payment link from your Tonkeeper wallet to send a transaction.
npm install qrcode-terminal
Finally, we’ll need to encode the payment link(link
) into the QR code and print it in the console. This is completed by following the steps below:
const qrcode = require('qrcode-terminal');
qrcode.generate(link, {small: true}, function (qrcode : any) {
console.log('🚀 Link to mine your NFT (use Tonkeeper in testnet mode):')
console.log(qrcode);
console.log('* If QR is still too big, please run script from the terminal. (or make the font smaller)')
});
Do you sense the experience in the air? That's you, on your way to becoming a TVM developer.
Now that we have successfully encoded the QR code generator and payment link, we'll need to acquire some Testnet Toncoins to send our first transaction. This is accomplished by making use of a TON token faucet (a Telegram Bot that shares Testnet Toncoins) on TON Blockchain, so we are in possession of some tokens that can be sent to the Tonkeeper wallet we created.
⛏ Mine an NFT With a Wallet
There are two main ways to mine an NFT on TON:
Simple: NFT Testnet Mining
Below are the steps needed to initiate your first Testnet transaction to mine your NFT:
- Activate Testnet mode within your Tonkeeper wallet
- Input our testnet wallet address from Tonkeeper into
wallet
variable in theindex.ts
- Input address of the NFT collection from Testnet into
collection
variable in theindex.ts
Top Up Wallet Balance via the Token Faucet
To proceed to the next step, we need to acquire some TON testnet tokens. This can be achieved by making use of the testnet faucet found here.
Mine A Testnet NFT Rocket
In order to successfully mine an NFT rocket on Testnet, it is necessary to follow these steps:
- Open Open the Tonkeeper wallet on your phone (it should hold some newly received TON Testnet tokens).
- Select scan mode in the wallet to scan the QR code.
- Run your miner to acquire the correct hash (this process takes between 30 and 60 seconds).
- Scan the generated QR code from the miner.
Because there may be other developers carrying out the same process in an attempt to mine their own NFT, you may have to try the process a couple times to be successful (as another user could mine the next NFT available right before you).
Soon after initiating this process, you will have successfully mined your very first NFT on TON (it should appear in your Tonkeeper wallet).
Welcome aboard, a true TVM Developer! You did it. 🛳
Genuine: NFT Mainnet Mining
Hey! For those who wish to mine an NFT on TON Mainnet, these instructions should be followed:
- You have activated mainnet mode in your Tonkeeper (it should hold at least 0.1 TON).
- Input our mainnet wallet address from Tonkeeper into
wallet
variable in theindex.ts
- Input address of the NFT collection from the Mainnet into
collection
variable in theindex.ts
- Replace endpoint to the Mainnet, for orbs-access it enables with excluding testnet argument in getHttpEndpoint:
// get the decentralized RPC endpoint in Mainnet
const endpoint = await getHttpEndpoint();
Mine A Mainnet NFT Rocket
Like we outlined in the testnet NFT rocket mining process, in order to successfully mine an NFT rocket on mainnet, it is necessary to follow these steps:
- Open the Tonkeeper wallet on your phone (remember, it should hold some TON tokens).
- Select scan mode in the wallet to scan the QR code.
- Run your miner to acquire the correct hash (this process takes between 30 and 60 seconds).
- Scan the generated QR code from the miner.
Because there may be other developers carrying out the same process in an attempt to mine their own NFT, you may have to try the process a couple times to be successful (as another user could mine the next NFT available right before you).
After some time, you will have mined your NFT and become a TVM Developer in TON Blockchain. The ritual is complete. Look at your NFT in Tonkeeper.
Welcome aboard, a TVM Developer! You did it. 🛳
🧙 What's next?
First, take a rest! You did a big task! You are a TVM developer now. But it's only the beginning of the long way.
See Also
After finishing the TON Onboarding Challenge where we successfully mined an NFT, consider taking a look at some of these materials that detail different portions of TON's Ecosystem:
- What is blockchain? What is a smart contract? What is gas?
- TON Hello World: Step-by-step guide for writing your first smart contract
- Develop Smart Contracts: Introduction
- [YouTube] Ton Dev Study - FunC & Blueprint
- How to work with wallet smart contracts
- FunC Journey: Part 1
- Bot for sales of dumplings
- Mint Your first Jetton
- Step by step NFT collection minting
- How to run TON Site
You are one of the first explorers here. If you find any mistakes or feel stacked, please send feedback to @SwiftAdviser. I will fix it ASAP! :)