How To Deploy a Smart Contract on TON Network?

FABC LLC
6 min readAug 28

--

learn to deploy ton network with simple steps

INTRODUCTION

The TON (Telegram Open Network) was a blockchain platform developed by Telegram, aiming to provide fast and scalable decentralized applications. Its unique features included a Byzantine Fault Tolerant consensus mechanism and off-chain processing. TON’s potential use lies in supporting high-speed, low-cost transactions, enabling complex DApps and smart contracts, and enhancing digital identity verification, all vital for Web 3.0 applications seeking efficient, secure, and scalable solutions.

In this blog, we will guide you through creating a smart contract on the TON network, offering a clear and concise walkthrough of the necessary tools, coding techniques, and deployment procedures. By the end, you’ll have a comprehensive understanding of how to bring your smart contract to life on this platform.

Here are the steps to create a smart contract on the TON network

To define your first smart contract on the TON network and set up your local machine for development, follow these steps:

  1. Install Prerequisites:
  • Make sure you have a compatible operating system (usually Linux).
  • Install JavaScript with the recent version of Node JS.
  • Install a code editor like Visual Studio Code with FunC for coding your smart contract Also install the FunC plugin.

2. Setup TON SDK:

  • Visit the TON SDK repository on GitHub.
  • Follow the installation instructions for your chosen operating system to install the TON SDK.

3. Setup the project:

Create a new directory with

npm install ts-node

npm install @ton-community/func-js

To install the library, deploy our contract and interact with it

npm install ton ton-crypto ton-core

4. Start with creating storage, messages & getter sections:

(int) load_data() inline {                 ;; read function declaration - returns int as result
var ds = get_data().begin_parse(); ;; load the storage cell and start parsing as a slice
return (ds~load_uint(64)); ;; read a 64 bit unsigned int from the slice and return it
}

() save_data(int counter) impure inline { ;; write function declaration - takes an int as arg
set_data(begin_cell() ;; store the storage cell and create it with a builder
.store_uint(counter, 64) ;; write a 64 bit unsigned int to the builder
.end_cell()); ;; convert the builder to a cell
}
() recv_internal(int msg_value, cell in_msg, slice in_msg_body) impure {  ;; well known function signature
if (in_msg_body.slice_empty?()) { ;; check if incoming message is empty (with no body)
return (); ;; return successfully and accept an empty message
}
int op = in_msg_body~load_uint(32); ;; parse the operation type encoded in the beginning of msg body
var (counter) = load_data(); ;; call our read utility function to load values from storage
if (op == 1) { ;; handle op #1 = increment
save_data(counter + 1); ;; call our write utility function to persist values to storage
}
}
int counter() method_id {        ;; getter declaration - returns int as result
var (counter) = load_data(); ;; call our read utility function to load value
return counter;
}

To use func-js packages run the following in the terminal

npx func-js counter.fc --boc counter.cell

Create an initial data cell for the deployment(counter.ts)

import { Contract, ContractProvider, Sender, Address, Cell, contractAddress, beginCell } from "ton-core";

export default class Counter implements Contract {

static createForDeploy(code: Cell, initialCounterValue: number): Counter {
const data = beginCell()
.storeUint(initialCounterValue, 64)
.endCell();
const workchain = 0; // deploy to workchain 0
const address = contractAddress(workchain, { code, data });
return new Counter(address, { code, data });
}

constructor(readonly address: Address, readonly init?: { code: Cell, data: Cell }) {}
}

Create a block of code to send messages for deployment

// export default class Counter implements Contract {

async sendDeploy(provider: ContractProvider, via: Sender) {
await provider.internal(via, {
value: "0.01", // send 0.01 TON to contract for rent
bounce: false
});
}

// }

5. Deploying the contract on the chain

First, install TON access with the following command

npm install @orbs-network/ton-access

Create a new script that will use the interface class(deploy.ts)

import * as fs from "fs";
import { getHttpEndpoint } from "@orbs-network/ton-access";
import { mnemonicToWalletKey } from "ton-crypto";
import { TonClient, Cell, WalletContractV4 } from "ton";
import Counter from "./counter"; // this is the interface class from step 7

async function deploy() {
// initialize ton rpc client on testnet
const endpoint = await getHttpEndpoint({ network: "testnet" });
const client = new TonClient({ endpoint });

// prepare Counter's initial code and data cells for deployment
const counterCode = Cell.fromBoc(fs.readFileSync("counter.cell"))[0]; // compilation output from step 6
const initialCounterValue = Date.now(); // to avoid collisions use current number of milliseconds since epoch as initial value
const counter = Counter.createForDeploy(counterCode, initialCounterValue);

// exit if contract is already deployed
console.log("contract address:", counter.address.toString());
if (await client.isContractDeployed(counter.address)) {
return console.log("Counter already deployed");
}

// open wallet v4 (notice the correct wallet version here)
const mnemonic = "unfold sugar water ..."; // your 24 secret words (replace ... with the rest of the words)
const key = await mnemonicToWalletKey(mnemonic.split(" "));
const wallet = WalletContractV4.create({ publicKey: key.publicKey, workchain: 0 });
if (!await client.isContractDeployed(wallet.address)) {
return console.log("wallet is not deployed");
}

// open wallet and read the current seqno of the wallet
const walletContract = client.open(wallet);
const walletSender = walletContract.sender(key.secretKey);
const seqno = await walletContract.getSeqno();

// send the deploy transaction
const counterContract = client.open(counter);
await counterContract.sendDeploy(walletSender);

// wait until confirmed
let currentSeqno = seqno;
while (currentSeqno == seqno) {
console.log("waiting for deploy transaction to confirm...");
await sleep(1500);
currentSeqno = await walletContract.getSeqno();
}
console.log("deploy transaction confirmed!");
}

deploy();

function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

Run it with the following command in your terminal

npx ts-node deploy.ts

Note down your deploy contract address.

Add the following code to counter.ts

// export default class Counter implements Contract {

async getCounter(provider: ContractProvider) {
const { stack } = await provider.get("counter", []);
return stack.readBigNumber();
}

// }

Executing the call(step5.ts):

import { getHttpEndpoint } from "@orbs-network/ton-access";
import { TonClient, Address } from "ton";
import Counter from "./counter"; // this is the interface class we just implemented

async function main() {
// initialize ton rpc client on testnet
const endpoint = await getHttpEndpoint({ network: "testnet" });
const client = new TonClient({ endpoint });

// open Counter instance by address
const counterAddress = Address.parse("EQBYLTm4nsvoqJRvs_L-IGNKwWs5RKe19HBK_lFadf19FUfb"); // replace with your address from step 8
const counter = new Counter(counterAddress);
const counterContract = client.open(counter);

// call the getter on chain
const counterValue = await counterContract.getCounter();
console.log("value:", counterValue.toString());
}

main();

Run the command in the terminal

npx ts-node step5.ts

6. Executing the send (step6.ts):

import { getHttpEndpoint } from "@orbs-network/ton-access";
import { mnemonicToWalletKey } from "ton-crypto";
import { TonClient, WalletContractV4, Address } from "ton";
import Counter from "./counter"; // this is the interface class we just implemented

async function main() {
// initialize ton rpc client on testnet
const endpoint = await getHttpEndpoint({ network: "testnet" });
const client = new TonClient({ endpoint });

// open wallet v4 (notice the correct wallet version here)
const mnemonic = "unfold sugar water ..."; // your 24 secret words (replace ... with the rest of the words)
const key = await mnemonicToWalletKey(mnemonic.split(" "));
const wallet = WalletContractV4.create({ publicKey: key.publicKey, workchain: 0 });
if (!await client.isContractDeployed(wallet.address)) {
return console.log("wallet is not deployed");
}

// open wallet and read the current seqno of the wallet
const walletContract = client.open(wallet);
const walletSender = walletContract.sender(key.secretKey);
const seqno = await walletContract.getSeqno();

// open Counter instance by address
const counterAddress = Address.parse("EQBYLTm4nsvoqJRvs_L-IGNKwWs5RKe19HBK_lFadf19FUfb"); // replace with your address from step 8
const counter = new Counter(counterAddress);
const counterContract = client.open(counter);

// send the increment transaction
await counterContract.sendIncrement(walletSender);

// wait until confirmed
let currentSeqno = seqno;
while (currentSeqno == seqno) {
console.log("waiting for transaction to confirm...");
await sleep(1500);
currentSeqno = await walletContract.getSeqno();
}
console.log("transaction confirmed!");
}

main();

function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}

Run the code with the following command

npx ts-node step6.ts

CONCLUSION:

Here in this blog, we have created a smart contract on the TON network.

To manage all these manual processes automatically use the development tool called Blueprint.

In the dynamic world of blockchain and decentralized technologies, the TON Network stands out as a revolutionary platform with immense potential. Embrace learning within the TON Network ecosystem offers unique benefits that can significantly contribute to your career growth.

FABC is the world's first web3.0 global company, our council is an embodiment of the community, encompassing the spectrum of innovators, change-makers, and pioneers. we are committed to Uncover blockchain’s core with hands-on lessons, making complex concepts accessible to all. Lay the groundwork for confident exploration in the blockchain realm. Learn more about us at FABC and discover how we’re contributing to the industry/solving problems/making a difference.

Connect with us for the latest updates and insights:

For inquiries, reach out to support@fabc.global@gmail.com.

--

--

FABC LLC

FABC-First Academy of Blockchain Council, The World's first global web 3.0 skill exchange platform.