Prerequisites
- Basic programming: variables, functions, if/else statements
- Basic familiarity with a command‑line interface and executing commands
- Node.js—
v22or later— download here- Check if installed:
node -vin terminal
- Check if installed:
- Installed TON wallet with Toncoin on testnet
Development environment
1
Set up development environment
Use the Blueprint development toolkit for smart contracts. Start a new project with:This command creates a project named “Example”, containing a contract named “FirstContract”.The generated project structure is:
Example/
├──contracts/ # smart contract source code
│ └── first_contract.tolk # main contract file
├── scripts/ # deployment and on-chain interaction scripts
│ └── deployFirstContract.ts # script to deploy the contract
├── tests/ # testing specifications
│ └── FirstContract.spec.ts # contract test file
├── wrappers/ # TypeScript wrappers for contract interaction
│ ├── FirstContract.ts # wrapper class for the smart contract
│ └── FirstContract.compile.ts # configuration for compiling contractThe TON ecosystem provides editor plugins with syntax support for IDEs and code editors. View them here.
2
Move into the project directory
What is a smart contract
A smart contract is a program stored on and executed by the . On-chain, every contract consists of two components:- Code — compiled TVM instructions, defines the contract’s logic.
- Data — persistent state, stores information between interactions.
Smart contract layout
A contract’s code consists of three functional sections: storage, messages, and get methods:- Storage holds the contract’s persistent state. Example: the
countervariable keeps its value across calls from different users. - Messages are receivers defined in the contract’s code that specify how the contract should react to each incoming message. Each message triggers a specific action or changes the state according to the contract’s logic.
- Get methods are read-only functions that return contract data without modifying state. Example: a get method that returns the current
countervalue.
Due to the TON architecture, get methods cannot be called from other contracts. Inter-contract communication uses messages only.
Write a smart contract
To build a simple counter contract:- Start with an initial
countervalue. - Send
increasemessages to add to the counter orresetmessages to set it to 0. - Call a get method to return the current
countervalue.
1
Define contract storage
Open the Structures serialize and deserialize automatically into cells, the storage unit in TON. The
./contracts/first_contract.tolk file.To define contract storage, store the counter value. Tolk makes it simple with :./contracts/first_contract.tolk
fromCell and toCell functions handle conversion between structures and cells.2
Implement message handlers
To process messages, implement the To avoid manual deserialization of each message, group the messages into a union. A union bundles multiple types into a single type and supports automatic serialization and deserialization.Now implement the message handler:
onInternalMessage function. It receives one argument — the incoming message. Focus on the body field, which contains the payload sent by a user or another contract.Define two message structures:IncreaseCounter— contains one fieldincreaseByto increment the counter.ResetCounter— resets the counter to 0.
0x7e8764ef and 0x3a752f06— called opcodes, that which allows the contract to distinguish between messages../contracts/first_contract.tolk
./contracts/first_contract.tolk
./contracts/first_contract.tolk
3
Add getter functions
Write a getter function to return the current counter:
./contracts/first_contract.tolk
4
Complete contract code
The contract now includes:
- Storage — persistent
countervalue - Messages —
IncreaseCounterandResetCounterhandlers - Get methods —
currentCounter
Full source code
Full source code
./contracts/first_contract.tolk
Compile the contract
To build the contract, compile it into bytecode for execution by the TVM. Use Blueprint with command:Deploy to testnet
1
Create a wrapper file
To deploy, create a wrapper class. Wrappers make it easy to interact with contracts from TypeScript.Open the Wrapper class details:
./wrappers/FirstContract.ts file and replace its content with the following code:./wrappers/FirstContract.ts
@ton/core— a library with base TON types.- The function
createFromConfigbuilds a wrapper using:- code — compiled bytecode
- data — the initial storage layout
- The contract address is derived deterministically from
codeanddatausingcontractAddress. - The method
sendDeploysends the first message withstateInit, the structure holding the contract’s initial code and data, which triggers deployment. In practice, this can be an empty message with Toncoin attached.
2
Choose the network
TON provides two networks for deployment:
- testnet — developer sandbox.
- mainnet — production blockchain.
3
Create the deployment script
Open the The
./scripts/deployFirstContract.ts file and replace its content with the following code.
It deploys the contract../scripts/deployFirstContract.ts
sendDeploy method accepts three arguments. Only two arguments are passed because provider.open automatically provides the ContractProvider as the first argument.4
Run the script
Funds at riskOn-chain deployments spend Toncoin and are irreversible. Verify the network before executing. Use testnet for practice; use mainnet only for actual deployment.
5
Confirm transaction
Wallet requiredIf a wallet is not installed, check the wallet section to select and install a wallet before deploying the contract. Make sure the wallet is funded with Toncoin on the testnet.
Contract interaction
Deployment also counts as a message sent to the contract. The next step is to send a message with a body to trigger contract logic.1
Update wrapper class
Update the wrapper class with three methods: The main difference from the deploy message is that these methods include a message body. The body is a cell that contains the instructions.Building message bodiesCells are constructed using the
sendIncrease, sendReset, and getCounter:./wrappers/FirstContract.ts
beginCell method:beginCell()creates a new cell builder.storeUint(value, bits)appends an unsigned integer with a fixed bit length.endCell()finalizes the cell.
beginCell().storeUint(0x7e8764ef, 32).storeUint(42, 32).endCell()- First 32 bits:
0x7e8764ef— opcode for “increase” - Next 32 bits:
42— increase by this amount
2
Send messages to the contract
With the contract deployed and wrapper methods in place, the next step is to send messages to it.Create a script Replace To run this script:Expected result:What happens during execution:
./scripts/sendIncrease.ts that increases the counter:./scripts/sendIncrease.ts
<CONTRACT_ADDRESS> with the address obtained in the deployment step.Funds at riskOn-chain deployments spend Toncoin and are irreversible. Verify the network before executing. Use testnet for practice; use mainnet only for actual deployment.
- Blueprint connects to the wallet using the TON Connect protocol.
- The script builds a transaction with a message body containing opcode
0x7e8764efand value42. - The wallet displays transaction details for confirmation.
- After approval, the transaction is sent to the network.
- Validators include the transaction in a newly produced block.
- The contract receives the message, processes it in
onInternalMessage, and updates the counter. - The script returns the resulting transaction hash; inspect it in the explorer.
ComposabilityOther contracts can also send messages to this contract. This enables composition: different contracts can combine their logic with this one, reuse it as a component, and build new behaviors that were not originally anticipated.
3
Reset the counter
To reset the counter, create a script To run this script:Expected result:
./scripts/sendReset.ts:./scripts/sendReset.ts
4
Read contract data with get methods
Get methods are special functions in TON smart contracts that run locally on a node. Unlike message-based interactions, get methods are:To run this script:Expected output:
- Free — no gas fees, as the call does not modify the blockchain state.
- Instant — no need to wait for blockchain confirmation.
- Read-only — can only read data; cannot modify storage or send messages.
getCounter(), which calls the contract’s getter provider.get('currentCounter'):./scripts/getCounter.ts
Get methods are available off-chain only — JavaScript clients, web apps, etc. — through RPC providers. Contracts cannot call getters on other contracts — inter-contract interaction uses only messages.
Funds at riskOn-chain deployments spend Toncoin and are irreversible. Verify the network before executing. Use testnet for practice; use mainnet only for actual deployment.