Why Foton

Why Foton?

This article explains the motivation behind the Foton project and its goals.

TL;DR: Developers struggle with the TON development ecosystem because of the lack of beginner-friendly and high-level tools. Foton aims to solve this problem by combining proven solutions from the Ethereum ecosystem with the best from TON.

Problem statement

The Open Network (TON) development ecosystem is fast-growing and constantly evolving. After years of development, it changed radically. As an example, the first smart contract language for TON was a low-level Fift. It was replaced some time later by the easier-to-understand FunC. These days, the community is working on a high-level Tact language, which brings high-level programming features to the TON smart contracts.

The situation with the JavaScript ecosystem in TON is the opposite to smart contracts. The long-standing libraries like @ton/core (opens in a new tab) and tonweb (opens in a new tab) are, in a way, low-level. They require deep understanding of TON blockchain and its architecture. To compose a transaction payload, developers need to know what are cells and slices, how to serialize them, etc. Moreover, documentation for the mentioned libraries is auto-generated and doesn't help with learning.

Existing libraries are not beginner-friendly. It creates a barrier for newcomers to start developing dApps on TON. As a result, the ecosystem looses potential developers and projects.

A better developer experience is crucial for the growth of the ecosystem.


Looking at the Ethereum ecosystem, we can see a real competition between the JavaScript libraries. This competition results in the best developer experience. It started with web3.js (opens in a new tab) in 2015, got overrun by a better alternative ethers.js (opens in a new tab). These days, the tools like Viem (opens in a new tab) and Thirdweb (opens in a new tab) are setting standards for the Ethereum JavaScript toolkits.

The libraries like Viem and Thirdweb abstract the complexity of the blockchain and export the API for real use cases: connecting to a wallet, sending transactions, deploying contracts, reading state, etc.

Foton takes the best from Ethereum and applies it to the best of TON.

Wallet connection before and after Foton

Foton simplifies TON development by reducing both the complexity and the amount of boilerplate code. Here is how a wallet would be connected before Foton:

import { TonConnectUI } from '@tonconnect/ui';
const tonConnect = new TonConnect({
  manifestUrl: '',
const connect = async () => {
  return new Promise((resolve, reject) => {
    tonConnect.onStatusChange((wallet) => {
      if (wallet) {
      } else {
const wallet = await connect();

Now, take a look at how easy it is to connect to any of supported wallets with Foton:

import { createWalletClientUI } from '@fotonjs/core';
export const walletClient = createWalletClientUI({
  manifestUrl: '',
const wallet = await walletClient.connect();

The snippet above creates a WalletClient instance and calls a connect method. In browser, user will see a modal with the list of supported wallets. They select one and immediately establish a connection.

Contract deployment before and after Foton

Before Foton, deploying a smart contract would require much low-level code and understanding of the TON blockchain. The amount of code would be overwhelming, maintaining it would be a nightmare.

Firstly, developers would need to construct a so-called stateInit cell representing the contract's code and initial state. Also, they would need to create a payload cell with the method arguments. Then, they would take a TON Connect instance (created in the previous section) and send a transaction:

import { beginCell, storeStateInit, toNano } from '@ton/core';
import { Counter } from './contracts/Counter';
import { tonConnect, userAddress } from './ton-connect';
const contract = Counter.fromInit();
const contractAddress = contract.address.toString();
const stateInitBuilder = beginCell();
storeStateInit({ code: contract.init!.code, data: contract.init!.data })(stateInitBuilder);
const stateInit = stateInitBuilder.endCell().toBoc().toString('base64');
const payloadBuilder = beginCell();
const queryId = BigInt(Math.floor(Math.random() * 1000));
payloadBuilder.storeUint(2490013878, 32);
payloadBuilder.storeUint(queryId, 64);
const payload = payloadBuilder.endCell().toBoc().toString('base64');
await tonConnect.sendTransaction({
  from: userAddress,
  validUntil: + 5 * 60 * 1000,
  messages: [
      address: contractAddress,
      amount: toNano('0.05'),

This code uses TON Connect and @ton/core and is surely difficult to understand. It composes cells in a non-JavaScript way while introducing "magical" numbers. The code is hard to maintain, debug, and scale.

In contrast, Foton keeps the deployment simple and readable:

import { createContractClient, parseTon } from '@fotonjs/core';
import { publicClient, walletClient } from './ton-clients';
import { Counter } from './contracts/Counter';
export const contractClient = createContractClient({
  contract: Counter,
const res = await counterClient.deploy({
  value: parseTon('0.05'),
  payload: { queryId: 1n },
  arguments: [],

In here, Foton uses the compilation result of the Tact or FunC compiler – a TypeScript class Counter describing the contract. This is all Foton needs to deploy, write and read from the contract. Thanks to compilers, this API provides even better developer experience that Viem. In Ethereum, developers would need to provide the ABI and contract code as a string, reducing readability.


Foton simplifies the TON dApp development by merging the best from Ethereum and TON together.

The provided examples show how Foton reduces complex, low-level code into straightforward, maintainable, and scalable solutions. By abstracting away the technical complexities, Foton allows developers to focus on building effective and innovative dApps.

Newcomers should be encouraged to try Foton for their next TON projects. It will help the ecosystem grow and attract more developers.