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
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 contractWhat 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.
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.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
Add getter functions
Write a getter function to return the current counter:
./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
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.
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.Run the script
TON provides two networks for deployment:Run the script with:For flags and options, see the Blueprint deployment guide.
- testnet — developer sandbox.
- mainnet — production blockchain.
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.
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.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
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.
Reset the counter
To reset the counter, create a script To run this script:Expected result:
./scripts/sendReset.ts:./scripts/sendReset.ts
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:After resetting the counter, the 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.