Skip to main content
This guide walks you through integrating Toncoin (TON) into your centralized exchange infrastructure. You’ll learn how to:
  • Create and fund a testnet wallet
  • Deploy and sync a liteserver node
  • Connect SDKs to your own node and Toncenter API
  • Simulate trace flows and handle deposit or withdrawal logic
  • Monitor transaction finality and infrastructure health
This guide is designed for backend engineers working on CEX infrastructure from MVP integration to production readiness.

Prerequisites

Before starting the integration process, make sure your environment meets the following:

System requirements

  • macOS, Linux, or WSL (Windows Subsystem for Linux)
  • Git and curl installed
  • Telegram account (used for faucet access)

Node hardware requirements

  • CPU: 16 cores minimum
  • RAM: 128 GB
  • Storage: 1 TB+ NVMe SSD (64,000+ IOPS)
  • Bandwidth: 1 Gbps, 16 TB monthly traffic budget
  • Network: Static public IP address

Provider requirements

For production, use self-hosted or dedicated bare-metal servers. If using cloud, choose from the recommended providers list and ensure consistent IOPS, high throughput, and a fixed public IP.

Hot wallet setup

Before integrating TON into your backend, you’ll need a hot wallet to run test transactions. A hot wallet is a cryptocurrency wallet that stays connected to the internet, enabling fast transactions. This differs from a cold wallet, which remains offline for long-term storage and maximum security. There are different ways to create hot wallets in TON, and you can choose any method that fits your workflow, but for simplicity, we will use Tonkeeper.
Testnet wallets should only be used for development. For production, switch to mainnet to ensure accurate fee calculation, transaction finality, and live trace verification.

Create wallet with Tonkeeper

Tonkeeper is a widely used TON mobile wallet that allows you to create a working address in minutes, which you can later import into your SDK for automated testing. To use Tonkeeper:
  1. Download the Tonkeeper mobile app.
  2. Go to Settings → Wallets → Add Wallet → Testnet Account.
  3. Save the 24-word seed phrase securely and copy the generated wallet address.
Your TON wallet address can be represented in two formats:
  • Base64 address – A user-friendly, encoded version designed for readability and safety. This format includes a checksum to help prevent errors when copying or sending funds.
    Example (Base64): UQBlXWdp1eP7W8RGeaH4vM86Y/8rT1hY+7XfF1t4dKQ=
  • Raw HEX address – The low-level representation containing the workchain ID and account ID. This is the direct blockchain reference to your wallet’s smart contract and is used in technical or SDK-based operations.
    Example (Raw HEX): -1:fcb91a3a3816d0f7b8c2c76108b8a9bc5a6b7a55bd79f8ab101c52db29232260
You can use the TON Address Tool to convert between formats and view mainnet or testnet variations.

Request testnet Toncoin

Every transaction on TON requires a small amount of Toncoin to cover network gas and forwarding fees. Before you can test deposits, withdrawals, or fee estimation, you’ll need to fund your hot wallet with testnet TON. There are two main ways to do this: For CEX integration testing, the most reliable method is to request Testnet funds directly from the TON Support team on Telegram. This way, you’ll have enough balance to run tests continuously without frequent top-ups.

Option B – Telegram faucet (Quick Start)

If you only need a small amount for initial or manual testing, use the public faucet:
  1. Open Telegram and start the @test_giver_ton_bot.
  2. Paste your testnet wallet address. The bot will send 2 TON to your address.
You can only request once per hour. For repeated or automated testing, use Option A to get a larger Testnet allocation and avoid interruptions.

Verify balance via explorer

After requesting TON, confirm that your wallet has been funded by using one of these official testnet explorers: Paste your wallet address into the search bar. You should see:
  • Balance: 2 TON (or more, if you’ve made repeated requests)
  • Address: (your wallet address)
  • State: uninit or inactive
If you see nonexist, it means the balance of the account is 0 or the contract does not have any data.

Core infrastructure: nodes and indexers

To support deposits and withdrawals on TON, your exchange backend needs reliable access to both read blockchain state (balances, account status, confirmations) and write transactions (relaying signed deposits, withdrawals, or contract calls). This requires running a node with liteserver enabled.

Node modes

A node can operate in two modes:
ModeDescriptionSuitable forLimitationsExample Use Case
Non-archivalKeeps only recent blockchain state; older history is pruned automatically.Everyday deposit and withdrawal processing where only the latest account state matters.Cannot retrieve or verify old transactions. History beyond the retention window is unavailable.Verifying a user deposit made in the last few blocks before crediting their balance.
ArchivalStores the full blockchain history. Can optionally use TTL/expiry settings to limit how long old data is retained.Compliance, audits, dispute resolution, or reconstructing account history months later.Higher storage and infrastructure requirements. If TTL is configured, very old history may still be dropped.A regulator requests proof of deposits from one year ago, or a customer disputes a withdrawal made six months earlier.
For production exchanges, an archival node is strongly preferred. It ensures access to the full transaction history, which is critical for compliance and customer support. Non-archival nodes can serve lightweight setups but impose strict limits on historical queries.

Deployment options

You can provision a node in two ways:
  • Run your own node : Install MyTonCtrl in archival or non-archival mode on dedicated infrastructure. Provides full control over synchronization, networking, and security policies.
  • Rent a dedicated node : Providers such as TON Center offer fully configured archival and non-archival nodes. This removes operational overhead while still giving you API access to the blockchain.

API layers

Nodes expose a liteserver endpoint, but it uses a low-level binary protocol that is not practical for exchange integration. Instead, TON Center APIs provide higher-level, developer-friendly access:
  • v2 API : Real-time account state and transaction submission over HTTP/JSON. Optimized for deposit and withdrawal flows where balances and finality must be verified quickly.
  • v3 API : Indexed blockchain history (transactions, traces, receipts) powered by the TON Indexer and PostgreSQL. Essential for large-scale queries, compliance reporting, and customer dispute resolution.
Best Practice
  • Use v2 for operational flows (deposits, withdrawals, balance checks).
  • Use v3 for historical data, compliance, and large-scale reporting.
  • Cross-check critical fields (e.g. transaction hash, block height, finality) across both APIs to combine cryptographic trust with query efficiency.

Install archival node with liteserver

Follow these steps to install and configure an archival node with liteserver using MyTonCtrl.

Step 1 - Prepare storage (ZFS)

  1. Install ZFS:
sudo apt install zfsutils-linux
  1. Create a pool on your dedicated <disk> named data:
sudo zpool create data <disk>
  1. Enable compression:
sudo zfs set compression=lz4 data
  1. Create a dataset and mount it at /var/ton-work:
sudo zfs create data/ton-work
sudo zfs set mountpoint=/var/ton-work data/ton-work

Step 2 - Install MyTonCtrl

Download and run the installer:
wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh
sudo bash install.sh
During setup:
  • Select liteserver mode and choose the network.
  • When prompted Do you want to download archive blocks via TON Storage?, enter 1 to set up an archive node.
  • Run installation in the background when asked, as archive sync can take several days.

Step 3 - Run and sync

After installation, the node will download and import all blocks. This may take weeks depending on hardware.

Step 4 - Verify sync status

Check synchronization with MyTonCtrl:
mytonctrl
MyTonCtrl> last
Example output:
last_masterchain_block: (seqno: 20498563)
peers: 7
is_working: true
There,
  • last_masterchain_block: latest block your node has synced
  • peers: number of connected nodes (ideally >3)
  • is_working: confirms the node is actively syncing
To confirm the node isn’t lagging, compare block height against a public explorer: If your node is within 1–2 blocks, it’s considered healthy.

Optional — Cross-check with Toncenter API

You can also verify your node’s sync against Toncenter’s v3 API: Example response:
{
  "last": {
    "seqno": 20498563,
    "shard": "-9223372036854775808",
    "workchain": -1
  }
}
If peers = 0 or is_working = false, check that the correct ports are open, the -d flag was used during install, and your server has a static IP with stable internet.

Step 6 - Connect SDKs to your liteserver

Once your node is running and synced, you can connect to it using SDKs in your backend. This allows you to:
  • Query account states
  • Track transactions
  • Fetch traces

Generate your config file

Inside the MyTonCtrl CLI, run:
MyTonCtrl> clcf
This generates a config file at: /usr/bin/ton/local.config.json Copy this file into your project directory (or rename it to config.json).

Per-language SDK setup

go get github.com/xssnick/tonutils-go
go get github.com/xssnick/tonutils-go/lite
go get github.com/xssnick/tonutils-go/ton
package main

import (
    "context"
    "encoding/json"
    "io/ioutil"
    "log"

    "github.com/xssnick/tonutils-go/liteclient"
    "github.com/xssnick/tonutils-go/ton"
)

func main() {
    client := liteclient.NewConnectionPool()

    // Load config
    content, err := ioutil.ReadFile("./config.json")
    if err != nil {
        log.Fatal("Failed to open config:", err)
    }

    var config liteclient.GlobalConfig
    if err := json.Unmarshal(content, &config); err != nil {
        log.Fatal("Failed to parse config:", err)
    }

    // Connect to node
    if err := client.AddConnectionsFromConfig(context.Background(), &config); err != nil {
        log.Fatal("Connection failed:", err)
    }

    api := ton.NewAPIClient(client)

    master, err := api.GetMasterchainInfo(context.Background())
    if err != nil {
        log.Fatal("Masterchain query failed:", err)
    }

    log.Println("Masterchain info:", master)
}
pip install pytonlib
from pytoniq import LiteClient

async def main():
    # Choose testnet or load custom config
    client = LiteClient.from_mainnet_config(
        ls_i=0,
        trust_level=2,
        timeout=15
    )

    await client.connect()
    info = await client.get_masterchain_info()
    print(info)
    await client.close()

# You can also use a context manager:
# async with LiteClient.from_mainnet_config(...) as client:
#     await client.get_masterchain_info()

# To connect to your own config:
# client = await LiteClient.from_file("config.json")
npm install ton-core ton-lite-client
import { LiteSingleEngine } from 'ton-lite-client/dist/engines/single.js'
import { LiteRoundRobinEngine } from 'ton-lite-client/dist/engines/roundRobin.js'
import { Lite } from 'ton-lite-client/dist/index.js'
import config from './config.json' assert {type: 'json'}

function intToIP(int) {
    return [
        (int >> 24) & 255,
        (int >> 16) & 255,
        (int >> 8) & 255,
        int & 255
    ].join(".");
}

const server = config.liteservers[0];

async function main() {
    const engine = new LiteRoundRobinEngine([
        new LiteSingleEngine({
            host: `tcp://${intToIP(server.ip)}:${server.port}`,
            publicKey: Buffer.from(server.id.key, 'base64'),
        }),
    ]);

    const client = new Lite({ engine });
    const master = await client.getMasterchainInfo();
    console.log("Masterchain info:", master);
}

main();
You’re now connected. Your backend is querying live data from your own node’s liteserver. This gives you full control over how and when data is fetched.
I