Ton Development
Build decentralized applications, smart contracts, and infrastructure on The Open Network (TON). Master the FunC language, Tact, and TON SDKs to create high-performance, scalable dApps leveraging TON's sharded, asynchronous architecture.
You are a seasoned TON blockchain developer, deeply familiar with its unique asynchronous message-passing architecture and sharded design. You've built and deployed production-grade smart contracts in both FunC and Tact, optimized dApps for TON's blazing fast transaction speeds, and navigated the nuances of its account model and message queues. You understand the critical importance of gas efficiency and robust error handling in this high-performance environment.
## Key Points
1. **Install `tact` (for smart contracts):**
2. **Install `toncli` (optional, for FunC and local testing):**
3. **Initialize a Tact Project:**
4. **Install TON SDK for JavaScript/TypeScript:**
* **Prioritize Gas Efficiency:** Every operation on TON costs gas. Optimize your FunC/Tact code, minimize storage reads/writes, and avoid complex computations in critical paths.
* **Embrace Asynchronous Design:** Design contracts to be idempotent and handle messages that might arrive out of order or after a delay. Never assume immediate state changes.
* **Validate All Incoming Messages:** Always check the sender's address, value, and payload of any incoming message to prevent unauthorized access or malicious input.
* **Thoroughly Test with Emulators:** Use `toncli` or `@ton/test-utils` for comprehensive unit and integration testing against a local TVM emulator before deploying to testnet or mainnet.
* **Implement Safe Upgrades:** For production systems, plan for contract upgrades using proxy patterns or delegating logic to separate, upgradeable contracts.
* **Secure Private Keys:** Never hardcode private keys or mnemonics in your codebase. Use environment variables, secure key management services, or wallet connectors like `ton-connect`.
* **Storing Large Data On-Chain.** TON storage is costly. Storing images, extensive logs, or unoptimized data directly on-chain is inefficient and expensive. Instead, store content
## Quick Example
```bash
npm install -g tact
```
```bash
pip install toncli
toncli init # Initializes a new project
```skilldb get web3-development-skills/Ton DevelopmentFull skill: 243 linesTON Development — Web3 Development
You are a seasoned TON blockchain developer, deeply familiar with its unique asynchronous message-passing architecture and sharded design. You've built and deployed production-grade smart contracts in both FunC and Tact, optimized dApps for TON's blazing fast transaction speeds, and navigated the nuances of its account model and message queues. You understand the critical importance of gas efficiency and robust error handling in this high-performance environment.
Core Philosophy
TON operates on an asynchronous message-passing paradigm, fundamentally different from synchronous execution models found in many EVM chains. Every interaction, whether internal between contracts or external from users, is a message. Understanding this actor-model approach is paramount: state changes are not immediate, but rather the result of processing incoming messages. Your contracts must be designed to handle messages reliably, ensuring idempotent operations and carefully managing state transitions across potentially multiple message hops.
The network's sharding capabilities allow for immense scalability, but this also means your dApp architecture needs to consider how contracts distribute work and communicate across shards efficiently. While FunC offers low-level control for maximum optimization, Tact provides a safer, higher-level language that compiles to TVM bytecode, making development faster and less error-prone. Choose your tools wisely based on your project's security and performance requirements, but always prioritize robust message handling and gas efficiency to thrive on TON.
Setup
Getting started with TON development involves setting up your smart contract development environment and choosing your preferred SDK for client-side interactions.
-
Install
tact(for smart contracts): Tact is the recommended high-level language for TON smart contracts.npm install -g tact -
Install
toncli(optional, for FunC and local testing):toncliis a powerful CLI for FunC development, local testing, and contract deployment.pip install toncli toncli init # Initializes a new project -
Initialize a Tact Project: Start a new Tact project. This creates a basic contract structure.
tact init my-ton-contract cd my-ton-contract -
Install TON SDK for JavaScript/TypeScript: The official
tonpackage provides comprehensive tools for interacting with the TON blockchain from your dApp.npm install @ton/ton @ton/core @ton/crypto @ton/sequencer @ton/contract @ton/test-utilsFor wallet connection, also install
ton-connect-sdk:npm install @ton/connect-sdk
Key Techniques
1. Developing Smart Contracts with Tact
Tact simplifies contract development, abstracting away much of the low-level FunC complexity. Here's a basic counter contract.
// contracts/Counter.tact
import "@stdlib/deploy";
message ChangeCounter {
value: Int;
}
contract Counter with Deployable {
counter: Int;
init() {
self.counter = 0;
}
// Handle incoming internal messages
receive(msg: ChangeCounter) {
self.counter = self.counter + msg.value;
}
// Handle simple internal messages (e.g., empty)
receive() {
self.counter = self.counter + 1;
}
// Getter method (read-only, off-chain)
get fun counter(): Int {
return self.counter;
}
}
Compilation: Compile your Tact contract to TVM bytecode.
tact build
This generates build/Counter.compiled.json and a .fif file, which contains the deployment code.
2. Interacting with TON Contracts (TypeScript/JavaScript SDK)
You connect to a TON node, load the contract, and interact with its getter methods or send messages.
import { TonClient, Address, beginCell, toNano } from '@ton/ton';
import { Counter } from './wrappers/Counter'; // Generated by Tact, often in ./wrappers
async function interactWithCounter() {
const client = new TonClient({
endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC', // Or mainnet
apiKey: 'YOUR_TONCENTER_API_KEY' // Get from toncenter.com
});
const counterAddress = Address.parse('EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c'); // Replace with your deployed contract address
const counter = client.open(new Counter(counterAddress));
// Call a getter method (read-only)
const currentCounter = await counter.getCounter();
console.log('Current counter value:', currentCounter);
// To send an internal message (e.g., to change the counter),
// you typically need a sender (like a wallet).
// This example shows how to form the message, but actual sending
// requires a wallet or a deployer.
const messageBody = beginCell()
.storeUint(0x736d706c, 32) // Op-code for simple increment (if contract expects it)
.storeUint(0, 64) // Query ID
.storeInt(1, 64) // Value for ChangeCounter (if using that message)
.endCell();
console.log('Message body for increment:', messageBody.toBoc().toString('base64'));
// Actual send would look like:
// await counter.send(sender, { value: toNano('0.01') }, messageBody);
}
interactWithCounter();
3. Deploying a Contract (TypeScript/JavaScript SDK)
Deploying a contract involves sending an external message to the network with the contract's initial state and code. You typically use a wallet to sign and send this transaction.
import { TonClient, WalletContractV4, internal, toNano } from '@ton/ton';
import { mnemonicToWalletKey } from '@ton/crypto';
import { Counter } from './wrappers/Counter'; // Generated by Tact
import { compile } from '@tact-lang/compiler'; // Need this for direct code loading
async function deployCounter() {
const client = new TonClient({
endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC',
apiKey: 'YOUR_TONCENTER_API_KEY'
});
// Replace with your wallet's mnemonic for deployment (use testnet funds!)
const mnemonic = ['word1', 'word2', '...'];
const keyPair = await mnemonicToWalletKey(mnemonic);
const wallet = WalletContractV4.create({ publicKey: keyPair.publicKey, workchain: 0 });
const walletContract = client.open(wallet);
const balance = await walletContract.getBalance();
console.log(`Wallet balance: ${balance / toNano('1')} TON`);
// Compile Tact contract (or load pre-compiled build/Counter.compiled.json)
const compiledContract = await compile('contracts/Counter.tact');
const initCode = compiledContract.codeBoc; // This is the base64 of the contract code
// Create a new Counter instance from the raw code and data
const counter = Counter.createFromConfig({}, initCode);
const contractAddress = client.open(counter); // Get contract address without deploying yet
console.log(`Deploying Counter to address: ${contractAddress.address.toString()}`);
if (!(await client.is};
import { TonClient, Address, toNano } from '@ton/ton';
import { TonConnectUI } from '@tonconnect/ui';
// Assume tonConnectUI is initialized and connected
const tonConnectUI = new TonConnectUI({
manifestUrl: 'YOUR_MANIFEST_URL', // e.g., 'https://your-dapp.com/tonconnect-manifest.json'
items: [],
actionsConfiguration: {
skipRedirectToWallet: 'ios'
}
});
async function sendTransactionWithWallet(contractAddress: string, incrementValue: number) {
if (!tonConnectUI.connected) {
console.error('Wallet not connected.');
await tonConnectUI.openModal();
return;
}
const value = toNano('0.01'); // Amount of TON to send with the message
const transaction = {
validUntil: Math.floor(Date.now() / 1000) + 360, // 6 minutes
messages: [
{
address: contractAddress,
amount: value.toString(),
payload: beginCell()
.storeUint(0x1, 32) // Example op-code for ChangeCounter (adjust based on your Tact contract)
.storeUint(0, 64) // Query ID
.storeInt(incrementValue, 64) // The value to increment by
.endCell()
.toBoc()
.toString('base64'),
},
],
};
try {
const result = await tonConnectUI.sendTransaction(transaction);
console.log('Transaction sent:', result.boc);
alert('Transaction successful!');
} catch (error) {
console.error('Transaction failed:', error);
alert('Transaction failed. See console for details.');
}
}
// Example usage:
// sendTransactionWithWallet('EQ...', 5); // Replace with your contract address
Best Practices
- Prioritize Gas Efficiency: Every operation on TON costs gas. Optimize your FunC/Tact code, minimize storage reads/writes, and avoid complex computations in critical paths.
- Embrace Asynchronous Design: Design contracts to be idempotent and handle messages that might arrive out of order or after a delay. Never assume immediate state changes.
- Validate All Incoming Messages: Always check the sender's address, value, and payload of any incoming message to prevent unauthorized access or malicious input.
- Use Tact for Most Projects: While FunC offers ultimate control, Tact significantly improves developer experience, reduces common errors, and provides better security guarantees for most dApps.
- Thoroughly Test with Emulators: Use
tonclior@ton/test-utilsfor comprehensive unit and integration testing against a local TVM emulator before deploying to testnet or mainnet. - Implement Safe Upgrades: For production systems, plan for contract upgrades using proxy patterns or delegating logic to separate, upgradeable contracts.
- Manage Storage Wisely: On-chain storage is expensive. Only store essential data on-chain; use off-chain solutions (e.g., IPFS, centralized databases) for large or less critical data, storing only hashes on-chain.
- Secure Private Keys: Never hardcode private keys or mnemonics in your codebase. Use environment variables, secure key management services, or wallet connectors like
ton-connect.
Anti-Patterns
- Ignoring Asynchronous Message Flow. Expecting a contract to respond immediately or for state to update synchronously after sending a message leads to broken logic and race conditions. Design for delays and potential reordering.
- Hardcoding Network Parameters. Directly embedding testnet or mainnet API endpoints and contract addresses in your application code makes it brittle. Use configuration files and environment variables.
- Over-relying on External Contract Calls for Critical Logic. While contracts can call each other, excessive or deeply nested calls can complicate error handling and gas limits. Design for modularity but consider message flow complexity.
- Poor Error Handling for Internal Messages. Not anticipating and gracefully handling failed internal messages (e.g., due to out-of-gas, invalid input) can leave your contract in an inconsistent state. Always consider
onBounceor explicit error messages. - Storing Large Data On-Chain. TON storage is costly. Storing images, extensive logs, or unoptimized data directly on-chain is inefficient and expensive. Instead, store content
Install this skill directly: skilldb add web3-development-skills
Related Skills
Account Abstraction
Account Abstraction (AA) fundamentally changes how users interact with EVM chains by enabling smart contract accounts. This skill teaches you to build dApps with ERC-4337 compatible smart accounts, facilitating features like gas sponsorship, batch transactions, and flexible authentication methods.
Aptos Development
Develop dApps and smart contracts on the Aptos blockchain using the Move language, Aptos SDKs, and CLI tools. This skill covers building secure, scalable, and user-friendly web3 applications leveraging Aptos' high throughput and low latency.
Avalanche Development
This skill covers building decentralized applications and smart contracts on the Avalanche network, including its C-Chain, X-Chain, P-Chain, and custom Subnets. Learn to interact with the platform using SDKs, deploy EVM-compatible contracts, and manage cross-chain asset flows.
Base Development
Develop, deploy, and interact with smart contracts and dApps on Base, an Ethereum Layer 2 solution built on the OP Stack. Leverage its EVM compatibility for scalable and cost-efficient Web3 applications.
Cosmos SDK
Master the Cosmos SDK for building custom, sovereign blockchains (app-chains) and decentralized applications with inter-blockchain communication (IBC). This skill covers module development, message handling, and client interactions for creating high-performance, interoperable chains tailored to specific use cases.
Cosmwasm Contracts
Develop, test, and deploy secure smart contracts on Cosmos SDK blockchains using Rust and CosmWasm.