Skip to main content

Reading from network

Introduction

This guide will walk you through reading data from TON Blockchain. You'll learn how to:

  • Fetch account information
  • Call get methods
  • Retrieve account transactions

By the end, you'll understand how to interact with TON HTTP-based APIs. In this guide, TON Center is used—a fast and reliable HTTP API for TON.

Set up environment

First, visit the installation pages and install Node.js and npm for your OS. Check that the installation is correct by running the following commands:

node -v
npm -v

Versions of node and npm should be at least v20 and v10 correspondingly.

Project setup

Let’s set up your project structure:

  1. Create a new directory for your project and navigate into it.
  2. Initialize a Node.js project.
  3. Install the required dependencies.
  4. Initialize TypeScript configuration.

Run these commands in your terminal:

mkdir reading-from-ton && cd reading-from-ton
npm init -y
npm install typescript ts-node @ton/ton @ton/core @ton/crypto
npx tsc --init

To run a TypeScript script saved as script.ts in your current directory, run:

npx ts-node script.ts

Reading account information

Account information includes the balance, state, code, and data.

  • balance: The amount of TON the account holds.
  • state: Can be one of:
    • Nonexist: The address has no data.
    • Uninit: The address has a balance but no smart contract code.
    • Active: The address is live with code and balance.
    • Frozen: The address is locked due to insufficient balance for storage costs.
  • code: The contract's code in raw format.
  • data: Serialized contract data stored in a Cell.

Account state may be obtained using the getContractState method.

Account's address

To get account information, you need the account's address. In TON, we can use a user-friendly address — a base64url-encoded string that represents a blockchain account in a human-readable and error-resistant format.

User-friendly addresses also include special flags that define how the address should be used. For example, some addresses are valid only on Testnet, while others work on any network. These flags are encoded in the first few bits and influence the first letter of the address:

  • Addresses beginning with E or U are used on Mainnet
  • Addresses beginning with k or 0 are used for Testnet

Mainnet example:

  • EQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPrHF
  • UQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPuwA

Testnet example:

  • kQDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPgpP
  • 0QDKbjIcfM6ezt8KjKJJLshZJJSqX7XOA4ff-W72r5gqPleK

Your address in the following examples

In the given code snippets, feel free to change the example address to your test wallet address in this line.

 // Replace with any address
const accountAddress = Address.parse('0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A-');

Implementation

Create a new file 1-get-account-state.ts:

1-get-account-state.ts
import { Address, TonClient } from "@ton/ton";

async function main() {
// Initializaing TON HTTP API Client
const tonClient = new TonClient({
endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC',
});

// Replace with any address
const accountAddress = Address.parse('0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A-');

// Calling method on http api
const state = await tonClient.getContractState(accountAddress);


console.log('State: ', state.state);
console.log('Balance: ', state.balance);
console.log('Data: ', state.data?.toString('hex'));
console.log('Code: ', state.code?.toString('hex'));
}

main();

Run this example using the following command:

npx ts-node 1-get-account-state.ts

Expected result

State:  active
Balance: 3722511000883n
Data: b5ee9c7241010101002...fd1e976824402aa67b98
Code: b5ee9c7241021401000...c9ed54696225e5

Note: the balance may differ from the example because anyone can send funds to the wallet, so the amount is dynamic and not fixed.

Calling get methods

Get methods are special functions in smart contracts that allow you to conveniently observe the current state of a smart contract, returning only the specific data you need—without having to read the entire account state, as we did in the first example. While reading the whole account provides you with all the information, including balance, code, data, and more, get methods allow you to query precise pieces of information, making the process more efficient and developer-friendly.

Their execution:

  • Do not charge any fees from contracts.
  • Cannot modify the smart contract’s storage or state.

The result of calling a get method via the TON HTTP API is returned in a stack format, which can be deserialised step-by-step using functions like readNumber() or others, depending on the expected data type.

Why do we need this?

In TON, tokens or jettons are managed via separate contracts called Jetton wallets, which are linked to users' main wallet addresses. To interact with a user's tokens, we first need to know the address of their Jetton wallet contract.

The get_wallet_address get method on the Jetton master contract allows us to retrieve the verified Jetton wallet contract address for a given user's main wallet address.

In this example, we demonstrate how to call this method to obtain the user's Jetton wallet address.

Implementation

Create a new file 2-call-get-method.ts:

2-call-get-method.ts
import { Address, TonClient, TupleBuilder } from "@ton/ton";

async function main() {
// Initializaing TON HTTP API Client
const tonClient = new TonClient({
endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC',
});

// Building optional get method parameters list
const builder = new TupleBuilder();

// Replace with your address
builder.writeAddress(Address.parse('0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A-'));

const accountAddress = Address.parse('kQD0GKBM8ZbryVk2aESmzfU6b9b_8era_IkvBSELujFZPsyy')

// Calling http api to run get method on specific contract
const result = await tonClient.runMethod(
accountAddress, // address to call get method on
'get_wallet_address', // method name
builder.build(), // optional params list
);

// Deserializing get method result
const rawAddress = result.stack.readAddress();

console.log("Raw address:", rawAddress.toRawString());
console.log("User-friendly address:", rawAddress.toString({ bounceable: true, urlSafe: true, testOnly: true}));

}

main();

Run this example using the following command:

npx ts-node 2-call-get-method.ts

Expected result

Raw address: 0:25f2bf1ce8f83ed0c0fd73ea27aac77093cdcf900c750b071df7fb0288e019b2
User-friendly address: kQB11H0oDahylXlASZjiDtINlrS0PevVMsvtsbmKmvN5l9np

As you can see, the get method returns the contract address in two formats:

  • The raw address (hexadecimal format) is how TON represents addresses internally. It’s precise but not very human-friendly.
  • The user-friendly address is a readable, safer format designed for sharing and everyday use. It’s easier to work with in wallets and apps.

Both addresses point to the same contract — in this case, the Jetton wallet contract associated with the user’s wallet address.

Get methods may also be called using Tonviewer:

  1. Navigate to the get methods section.
  2. Select get_wallet_address.
  3. Insert the address from the example 0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A- into the slice section.
  4. Press Execute.

You will end up with the same address you got from the console.

Using wrappers for simplicity

Wrappers are classes that simplify interactions with smart contracts by turning complex blockchain operations into simple function calls. Instead of manually serializing cells and transactions, you can just call methods like jettonMaster.getWalletAddress() that already perform these tasks for you. Here's an example of using a wrapper functionally equivalent to the previous code snippet:

import { Address, JettonMaster, TonClient } from "@ton/ton";

async function main() {
// Initializaing TON HTTP API Client
const tonClient = new TonClient({
endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC',
});

// Initializing wrappers
const jettonMaster = tonClient.open(
JettonMaster.create(Address.parse('kQD0GKBM8ZbryVk2aESmzfU6b9b_8era_IkvBSELujFZPsyy')),
);

// Calling get method through wrapper
const address = await jettonMaster.getWalletAddress(Address.parse('0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A-'));
console.log(address);
}

main();

Fetching account transactions

Interaction within an account on the blockchain happens due to messages and transactions.

What is a transaction?

A transaction in TON consists of the following:

  • The incoming message that initially triggers the contract (special ways to trigger exist)
  • Contract actions caused by the incoming message, such as an update to the contract's storage (optional)
  • Outgoing messages generated and sent to other actors (optional)

Key transaction fields

A transaction obtained from the API has the following structure:

{
"address": {
"account_address": "EQD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje02Zx"
},
"utime": 1738588970,
...
"in_msg": {
...
},
"out_msgs": [...]
}
  • address: The account address where the transaction occurred.
  • utime: The unix timestamp of the transaction.
  • in_msg: The incoming message that triggered the transaction.
  • out_msgs: Outgoing messages sent during the transaction.

What is a message?

A message is a packet of data exchanged between actors (users, applications, or smart contracts). It typically contains information instructing the receiver on what action to perform, such as updating storage or sending a new message.

Key message fields

{
"hash": "mcHdqltDAB8ODQHqtedtYQIS6MQL7x4ut+nf9tXWGqg=",
"source": "EQAJTegD8OO-HksHfI4KVDqb7vW9Dlqi5C1FTcL1dECeosTf",
"destination": "EQD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje02Zx",
"value": "20000000",
...
"msg_data": {
"body": "te6cckEBAQEAAgAAAEysuc0=",
...
},
...
}
  • hash: A cryptographic message identifier which is computed after the message is included in a transaction and assigned a logical time (lt), which determines its processing order. The hash is not part of the original message and uniquely identifies the finalized message for integrity verification.
  • source: The address of the sender (the account that initiated the message).
  • destination: The address of the receiver (the account that will process the message).
  • value: The amount of TON (in nanoTON) attached to the message.
  • msg_data: Contains the message body and state initialization.

Implementation

Let’s now try to fetch transactions for an account we control.

Before running this code:

  • Go to Tonviewer and open your Testnet wallet address, which we created earlier in the Getting Started section.
  • Send some test TON to yourself using Testgiver Ton Bot.
  • Wait a few seconds and make sure the transaction appears in Tonviewer.
important

Make sure you're working in the Testnet, not the Mainnet.

Also, please note that the Testnet API may update data with some delay, so your transaction might not appear immediately when querying through the API.

  • Then, create a new file 3-fetch-account-transaction.ts:
3-fetch-account-transaction.ts
import { Address, TonClient } from "@ton/ton";

async function main() {
// Initializaing TON HTTP API Client
const tonClient = new TonClient({
endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC',
});

// Calling method on http api
// full api: https://testnet.toncenter.com/api/v2/#/accounts/get_transactions_getTransactions_get
const transactions = await tonClient.getTransactions(
// Replace with your Testnet address to fetch transactions
Address.parse('0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A-'),
{
limit: 10, //maximum ammount of recieved transactions
archival: true, //search in all history
},
);

const firstTx = transactions[0];
const { inMessage } = firstTx;

console.log('Timestamp:', firstTx.now);
if (inMessage?.info?.type === 'internal') {
console.log('Value:', inMessage.info.value.coins);
console.log('Sender:', inMessage.info.src.toString({ testOnly: true }));
}
}

main();
  • Replace Address.parse('0QD-SuoCHsCL2pIZfE8IAKsjc0aDpDUQAoo-ALHl2mje04A-') with your Testnet address.

Run this example using the following command:

npx ts-node 3-fetch-account-transaction.ts

Expected result

Timestamp: 1748338158
Value: 48526800n
Sender: kQDhJ2Kx7dD6FLzAXcqiI4Xsu4ioY6JlE24m9Tx86eGkq0OF
info

A more complex example of traversing transactions graph may be found here.

Next step

Now that you’ve learned how to read data from TON Blockchain, it’s time to explore how to write data to the network.

Click the button below to continue:

Writing to the network

Was this article useful?