A local TON blockchain sandbox with a desktop inspection GUI.
Pontoon runs a real @ton/sandbox TVM emulator under a JSON-RPC bridge and puts a Tauri desktop UI on top of it — the visual layer over local TON contract development. Think Ganache for TON, with a Tenderly-grade transaction inspector.
Every panel talks to a live Blockchain instance: real fees, real per-phase compute/action breakdowns, real VM step traces, real snapshots and time travel. Nothing is canned.
Pontoon Studio is a 20-panel workbench grouped into four areas:
| Group | Panels |
|---|---|
| Workspace | Workspace manager · Accounts · Contracts |
| Execution | Message sender · Get-method runner · Transaction inspector · Block explorer · State inspector |
| Environment | Time control · Snapshot manager · Fork mode · Network config · Libraries |
| Diagnostics | Logs console · Coverage · Benchmark · Step debugger · MITM · Determinism · Test runner |
Highlights:
- Transaction inspector — full message-tree with per-phase fees and exit codes, modeled on Tenderly + Tonviewer.
- TVM step debugger — step through opcodes with synchronized stack/gas views (Remix-style).
- Snapshot manager — branch, diff, and revert chain state (PlanetScale/Neon-style branching).
- Time control — manual clock; advance by seconds/years.
- Command palette — keyboard-first navigation (Linear/Raycast-style).
- Dual light/dark theme — near-black Linear-style dark, TON blue as the single accent.
pontoon/ pnpm + TurboRepo monorepo
├── apps/
│ ├── desktop/ @pontoon/app — Tauri + React 19 + Vite 6 + Tailwind 4 desktop GUI
│ │ ├── src/panels/ A1–A20 inspection panels
│ │ ├── src/rpc/ wire contract (57 methods), codec, message-tree types
│ │ └── src-tauri/ Tauri shell (spawns the bridge as a sidecar)
│ └── website/ marketing + docs site
└── packages/
├── bridge/ @pontoon/bridge — real @ton/sandbox JSON-RPC bridge (default)
└── mock-bridge/ @pontoon/mock-bridge — canned fixtures for fast offline UI work
The bridge (packages/bridge/) holds one live Blockchain.create() instance and implements the 57-method wire contract over WebSocket JSON-RPC (port 37631, protocol 1.0.0). It seeds two funded treasuries on boot. Files:
server.ts— WS server, handshake, JSON-RPC dispatch, subscriptionsstate.ts— theWorkspace(blockchain, accounts, tx history, snapshots, libs, seed)handlers.ts— all 57 methods across 14 namespacestree.ts—BlockchainTransaction[]→ message-tree (TxNode) +vm_logs_full→ VM stepsencode.ts— bigint↔decimal-string, Cell↔base64 BOC, address↔raw0:<hex>
The frontend never changes its wire contract — apps/desktop/src/rpc/contract.ts is the fixed boundary both bridges satisfy. Most capabilities are fully real; four that need a user's Blueprint project + toolchain (contract.deploy by wrapper, contract.abi from .abi.json, test.run, FunC/Tact source coverage) degrade gracefully with a clear "attach a Blueprint project" note and light up once one is attached.
Prerequisites: Node 20+, pnpm 10+. For the desktop build, a Tauri toolchain (Rust + platform deps).
pnpm installStarts the real @ton/sandbox bridge and the Vite UI together:
pnpm devThen open the printed Vite URL. The UI auto-connects to the bridge at 127.0.0.1:37631.
pnpm desktop:dev # Tauri dev shell over the live Vite + bridge stack
pnpm desktop:build # production bundle (installers under apps/desktop/src-tauri/target/release/bundle/)In dev the shell reuses the tsx bridge on 127.0.0.1:37631. Production bundles embed the bridge as a compiled sidecar binary instead: the shell generates a session token, starts the sidecar on an OS-assigned local port, waits for its READY <port> signal after sandbox warmup, injects window.__PONTOON_BRIDGE__, and kills the sidecar on exit — so a packaged app and a dev stack can run side by side.
Building the sidecar requires bun (it compiles packages/bridge plus the embedded TVM WASM into a self-contained binary via bun build --compile). Tauri/Cargo builds generate the required sidecar automatically before validating externalBin; the script can still be run directly when you want to prebuild a specific target:
pnpm sidecar:build # host platform
node scripts/build-sidecar.mjs --target <rust-triple> # cross-targetPushing a v* tag runs the release workflow: it builds the sidecar and installers for macOS (Apple silicon + Intel), Windows, and Linux, and uploads them to a draft GitHub Release. macOS artifacts are signed and notarized automatically once the APPLE_* secrets are configured; without them the build stays unsigned.
pnpm dev:mock # UI + canned-fixture mock bridge, no WASM startupAll scripts run through TurboRepo from the repo root.
| Command | What it does |
|---|---|
pnpm dev |
Real bridge + Vite UI |
pnpm dev:mock |
Mock bridge + Vite UI |
pnpm dev:ui |
UI only |
pnpm bridge |
Real bridge only |
pnpm build |
Build all packages |
pnpm tsc |
Type-check all packages |
pnpm lint |
Lint all packages |
pnpm test |
Test all packages |
pnpm desktop:dev / desktop:build |
Tauri desktop |
Bridge end-to-end smoke (drives a real treasury→treasury send and asserts real fees, VM steps, snapshot revert):
pnpm --filter @pontoon/bridge smoke- Desktop: Tauri 2
- UI: React 19, Vite 6, Tailwind 4, Zustand, TanStack Query, shadcn-style primitives on Radix
- Chain:
@ton/sandbox0.42,@ton/core0.63,@ton/ton - Transport: WebSocket JSON-RPC 2.0
- Tooling: pnpm workspaces + TurboRepo
DESIGN.md— UI design language and panel-by-panel reference.PRODUCT.md— product scope and the @ton/sandbox API → panel mapping.- The wire contract (
apps/desktop/src/rpc/) is the contract between UI and bridge — keep both bridges in lockstep with it.