First Steps
This guide walks you through the basics of using Ton.NET.
Choosing a Client
Ton.NET provides two ways to interact with TON blockchain:
LiteClient (Recommended)
- Direct node connection via ADNL protocol
- Fast and efficient - no HTTP overhead
- Automatic load balancing across multiple servers
- Best for production applications
using Ton.LiteClient;
// Automatically connects to TON network from global config
LiteClient client = await LiteClientFactory.CreateFromUrlAsync(
"https://ton.org/global-config.json"
);
HttpClient (Alternative)
- HTTP API via Toncenter or TON HTTP API v4
- Easier to debug with standard HTTP tools
- Good for prototyping and development
- May have rate limits on public endpoints
using Ton.HttpClient;
TonClient client = new(new TonClientParameters
{
Endpoint = "https://toncenter.com/api/v2",
ApiKey = "your-api-key" // optional for public endpoint
});
Basic Operations
Getting Blockchain Info
// Get latest masterchain block
MasterchainInfo info = await client.GetMasterchainInfoAsync();
Console.WriteLine($"Latest block seqno: {info.Last.Seqno}");
Console.WriteLine($"Workchain: {info.Last.Workchain}");
// Get extended info with capabilities
MasterchainInfoExt infoExt = await client.GetMasterchainInfoExtAsync();
Console.WriteLine($"Protocol version: {infoExt.Version}");
Console.WriteLine($"Server capabilities: {infoExt.Capabilities}");
Console.WriteLine($"Server time: {DateTimeOffset.FromUnixTimeSeconds(infoExt.Now)}");
Working with Addresses
TON addresses come in two formats:
using Ton.Core.Addresses;
// Parse friendly format (base64)
Address friendly = Address.Parse("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N");
// Parse raw format (workchain:hash)
Address raw = Address.Parse("0:83dfd552e63729b472fcbcc8c45ebcc6691702558b68ec7527e1ba403a0f31a8");
// Both represent the same address
Console.WriteLine(friendly.Equals(raw)); // true
// Convert to different formats
string friendlyStr = friendly.ToString(AddressType.Base64, bounceableTag: true);
string rawStr = friendly.ToString(AddressType.Raw);
Getting Account State
Address address = Address.Parse("EQCD39VS5jcptHL8vMjEXrzGaRcCVYto7HUn4bpAOg8xqB2N");
BlockId block = info.Last; // use latest block
AccountState state = await client.GetAccountStateAsync(address, block);
Console.WriteLine($"Address: {state.Address}");
Console.WriteLine($"Balance: {state.BalanceInTon:F4} TON");
Console.WriteLine($"State: {state.State}");
Console.WriteLine($"Is active: {state.IsActive}");
Console.WriteLine($"Is contract: {state.IsContract}");
if (state.Code != null)
{
Console.WriteLine($"Contract code hash: {Convert.ToHexString(state.Code.Hash(0))}");
}
Looking Up Blocks
// Lookup by seqno
BlockId block = await client.LookupBlockAsync(
workchain: -1, // masterchain
shard: -9223372036854775808, // full shard
seqno: 1000000
);
// Lookup by timestamp
BlockId blockByTime = await client.LookupBlockByUtimeAsync(
workchain: -1,
shard: -9223372036854775808,
utime: 1672531200 // Unix timestamp
);
// Lookup by logical time
BlockId blockByLt = await client.LookupBlockByLtAsync(
workchain: -1,
shard: -9223372036854775808,
lt: 1000000000
);
Listing Transactions in a Block
BlockId block = info.Last;
BlockTransactions txs = await client.ListBlockTransactionsAsync(block, count: 10);
Console.WriteLine($"Block has {txs.Transactions.Count} transactions");
Console.WriteLine($"Incomplete: {txs.Incomplete}");
foreach (var tx in txs.Transactions)
{
Console.WriteLine($"Account: {Convert.ToHexString(tx.AccountHash)}");
Console.WriteLine($"LT: {tx.Lt}");
Console.WriteLine($"Hash: {Convert.ToHexString(tx.Hash)}");
}
Error Handling
All methods can throw exceptions. Always use try-catch for production code:
try
{
AccountState state = await client.GetAccountStateAsync(address, block);
Console.WriteLine($"Balance: {state.BalanceInTon} TON");
}
catch (TimeoutException)
{
Console.WriteLine("Request timed out");
}
catch (InvalidOperationException ex)
{
Console.WriteLine($"Invalid operation: {ex.Message}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
Connection Management
LiteClient handles connections automatically:
- Connects on first request
- Reconnects automatically if disconnected
- No manual connection management needed
- Uses
Dispose()to clean up resources
// Use 'using' for automatic disposal
await using LiteClient client = await LiteClientFactory.CreateFromUrlAsync(
"https://ton.org/global-config.json"
);
// Client automatically connects and manages connection
// ... use client ...
// Automatically disposed at end of scope
Next Steps
- Learn about Key Concepts
- Explore LiteClient Guide
- Work with Cells and BOC
- Create Wallets and Send Transactions