ton/development-guide

TON Development Guide: FunC / Tact / Blueprint

tonguide👥 Communityconfidence highhealth -2%
v1.0.0·Updated 3/20/2026

⚠️ API call failed (attempt 1/3): RateLimitError [HTTP 429] 🔌 Provider: copilot Model: claude-sonnet-4.6 🌐 Endpoint: https://api.githubcopilot.com 📝 Error: HTTP 429: Sorry, you've exhausted this model's rate limit. Please try a different model. Please review our Terms of Service. 📋 Details: Sorry, you've exhausted this model's rate limit. Please try a different model. Please review our Terms of Service. ⚠️ Rate limited — switching to fallback provider... 🔄 Primary model failed — switching to fallback: anthropic/claude-sonnet-4-6 via custom:commonstack

TON Development Guide

TON Highlights

  • Deep Telegram Integration: 800M+ Telegram users, TON Space built-in wallet
  • Async Architecture: Contracts communicate via messages, unlike EVM's synchronous calls
  • Shardchain: Unlimited horizontal scaling, each contract has independent state
  • Jetton: TON's FT standard (similar to ERC-20, but with significant implementation differences)

Contract Language Options

LanguageCharacteristicsRecommendation
FunCLow-level, close to assembly, most existing contracts use thisUnderstanding internals
TactHigh-level language, TypeScript-like, safe and concisePreferred for new projects
BlueprintDevelopment framework (scaffolding + testing)Always use

Tact Contract Example

// counter.tact
import "@stdlib/deploy";

contract Counter with Deployable {
  owner: Address;
  counter: Int as uint32;

  init(owner: Address) {
    self.owner = owner;
    self.counter = 0;
  }

  receive("increment") {
    self.counter += 1;
  }

  receive(msg: ChangeOwner) {
    require(sender() == self.owner, "Only owner");
    self.owner = msg.newOwner;
  }

  get fun counter(): Int {
    return self.counter;
  }

  get fun owner(): Address {
    return self.owner;
  }
}

message ChangeOwner {
  newOwner: Address;
}

Blueprint Project

# Create project
npm create ton@latest my-project -- --type tact-counter
cd my-project && npm install

# Compile
npx blueprint build

# Test
npx blueprint test

# Deploy (requires wallet configuration)
npx blueprint run

Test Example

import { Blockchain, SandboxContract } from "@ton/sandbox"
import { Counter } from "../wrappers/Counter"
import { toNano } from "@ton/core"
import "@ton/test-utils"

describe("Counter", () => {
  let blockchain: Blockchain
  let counter: SandboxContract<Counter>

  beforeEach(async () => {
    blockchain = await Blockchain.create()
    const deployer = await blockchain.treasury("deployer")
    counter = blockchain.openContract(await Counter.fromInit(deployer.address))
    await counter.send(deployer.getSender(), { value: toNano("0.05") }, { $$type: "Deploy", queryId: 0n })
  })

  it("should increment", async () => {
    const user = await blockchain.treasury("user")
    await counter.send(user.getSender(), { value: toNano("0.01") }, "increment")
    expect(await counter.getCounter()).toBe(1n)
  })
})

Jetton (TON Token Standard)

The biggest difference between TON Jetton and ERC-20: each wallet address has its own dedicated JettonWallet contract.

Jetton Master (token info)
  ├── JettonWallet(Alice)  ← Alice's balance lives here
  ├── JettonWallet(Bob)
  └── JettonWallet(DEX)
// @ton/ton SDK
import { JettonMaster, JettonWallet } from "@ton/ton"

const client = new TonClient({ endpoint: "https://toncenter.com/api/v2/jsonRPC" })
const jettonMaster = client.open(JettonMaster.create(masterAddress))

// Get the user's JettonWallet address
const walletAddress = await jettonMaster.getWalletAddress(userAddress)
const jettonWallet = client.open(JettonWallet.create(walletAddress))

// Query balance
const { balance } = await jettonWallet.getWalletData()

// Transfer (send a message to your own JettonWallet)
const tx = internal({
  to: walletAddress,
  value: toNano("0.05"),  // gas
  body: JettonWallet.transferMessage(amount, recipient, responseAddress, null, toNano("0.01"), null),
})

TON Connect (Wallet Connection)

npm install @tonconnect/ui-react
import { TonConnectUIProvider, TonConnectButton, useTonConnectUI } from "@tonconnect/ui-react"

// App.tsx
<TonConnectUIProvider manifestUrl="https://your-app.com/tonconnect-manifest.json">
  <YourApp />
</TonConnectUIProvider>

// Usage
function App() {
  const [tonConnectUI] = useTonConnectUI()
  
  const sendTx = async () => {
    await tonConnectUI.sendTransaction({
      messages: [{
        address: recipientAddress,
        amount: toNano("0.1").toString(),
      }],
    })
  }
  
  return <TonConnectButton />  // Automatically handles Telegram built-in wallet + TON Space
}

tonconnect-manifest.json

{
  "url": "https://your-app.com",
  "name": "My TON App",
  "iconUrl": "https://your-app.com/icon.png"
}

Telegram Mini Apps Integration

import { retrieveLaunchParams } from "@telegram-apps/sdk"

// Get Telegram user info (already verified by Telegram)
const { initDataRaw, initData } = retrieveLaunchParams()
const user = initData?.user  // { id, firstName, lastName, username }

// Open TON Space payment
import { openLink } from "@telegram-apps/sdk"
openLink("ton://transfer/" + address + "?amount=" + amount + "&text=Payment")

Tool Ecosystem

ToolPurpose
BlueprintDevelopment framework (essential)
TON CenterPublic API node
TonviewerBlock explorer
TON SpaceTelegram built-in wallet
TonkeeperMainstream standalone wallet

TON Development Guide

TON Highlights

  • Deep Telegram Integration: 800M+ Telegram users, TON Space built-in wallet
  • Async Architecture: Contracts communicate via messages, unlike EVM's synchronous calls
  • Shardchain: Unlimited horizontal scaling, each contract has independent state
  • Jetton: TON's FT standard (similar to ERC-20, but with significant implementation differences)

Contract Language Options

LanguageCharacteristicsRecommendation
FunCLow-level, close to assembly, most existing contracts use thisUnderstanding internals
TactHigh-level language, TypeScript-like, safe and concisePreferred for new projects
BlueprintDevelopment framework (scaffolding + testing)Always use

Tact Contract Example

// counter.tact
import "@stdlib/deploy";

contract Counter with Deployable {
  owner: Address;
  counter: Int as uint32;

  init(owner: Address) {
    self.owner = owner;
    self.counter = 0;
  }

  receive("increment") {
    self.counter += 1;
  }

  receive(msg: ChangeOwner) {
    require(sender() == self.owner, "Only owner");
    self.owner = msg.newOwner;
  }

  get fun counter(): Int {
    return self.counter;
  }

  get fun owner(): Address {
    return self.owner;
  }
}

message ChangeOwner {
  newOwner: Address;
}

Blueprint Project

# Create project
npm create ton@latest my-project -- --type tact-counter
cd my-project && npm install

# Compile
npx blueprint build

# Test
npx blueprint test

# Deploy (requires wallet configuration)
npx blueprint run

Test Example

import { Blockchain, SandboxContract } from "@ton/sandbox"
import { Counter } from "../wrappers/Counter"
import { toNano } from "@ton/core"
import "@ton/test-utils"

describe("Counter", () => {
  let blockchain: Blockchain
  let counter: SandboxContract<Counter>

  beforeEach(async () => {
    blockchain = await Blockchain.create()
    const deployer = await blockchain.treasury("deployer")
    counter = blockchain.openContract(await Counter.fromInit(deployer.address))
    await counter.send(deployer.getSender(), { value: toNano("0.05") }, { $$type: "Deploy", queryId: 0n })
  })

  it("should increment", async () => {
    const user = await blockchain.treasury("user")
    await counter.send(user.getSender(), { value: toNano("0.01") }, "increment")
    expect(await counter.getCounter()).toBe(1n)
  })
})

Jetton (TON Token Standard)

The biggest difference between TON Jetton and ERC-20: each wallet address has its own dedicated JettonWallet contract.

Jetton Master (token info)
  ├── JettonWallet(Alice)  ← Alice's balance lives here
  ├── JettonWallet(Bob)
  └── JettonWallet(DEX)
// @ton/ton SDK
import { JettonMaster, JettonWallet } from "@ton/ton"

const client = new TonClient({ endpoint: "https://toncenter.com/api/v2/jsonRPC" })
const jettonMaster = client.open(JettonMaster.create(masterAddress))

// Get the user's JettonWallet address
const walletAddress = await jettonMaster.getWalletAddress(userAddress)
const jettonWallet = client.open(JettonWallet.create(walletAddress))

// Query balance
const { balance } = await jettonWallet.getWalletData()

// Transfer (send a message to your own JettonWallet)
const tx = internal({
  to: walletAddress,
  value: toNano("0.05"),  // gas
  body: JettonWallet.transferMessage(amount, recipient, responseAddress, null, toNano("0.01"), null),
})

TON Connect (Wallet Connection)

npm install @tonconnect/ui-react
import { TonConnectUIProvider, TonConnectButton, useTonConnectUI } from "@tonconnect/ui-react"

// App.tsx
<TonConnectUIProvider manifestUrl="https://your-app.com/tonconnect-manifest.json">
  <YourApp />
</TonConnectUIProvider>

// Usage
function App() {
  const [tonConnectUI] = useTonConnectUI()
  
  const sendTx = async () => {
    await tonConnectUI.sendTransaction({
      messages: [{
        address: recipientAddress,
        amount: toNano("0.1").toString(),
      }],
    })
  }
  
  return <TonConnectButton />  // Automatically handles Telegram built-in wallet + TON Space
}

tonconnect-manifest.json

{
  "url": "https://your-app.com",
  "name": "My TON App",
  "iconUrl": "https://your-app.com/icon.png"
}

Telegram Mini Apps Integration

import { retrieveLaunchParams } from "@telegram-apps/sdk"

// Get Telegram user info (already verified by Telegram)
const { initDataRaw, initData } = retrieveLaunchParams()
const user = initData?.user  // { id, firstName, lastName, username }

// Open TON Space payment
import { openLink } from "@telegram-apps/sdk"
openLink("ton://transfer/" + address + "?amount=" + amount + "&text=Payment")

Tool Ecosystem

ToolPurpose
BlueprintDevelopment framework (essential)
TON CenterPublic API node
TonviewerBlock explorer
TON SpaceTelegram built-in wallet
TonkeeperMainstream standalone wallet
GetGemsNFT marketplace