> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ton.org/llms.txt
> Use this file to discover all available pages before exploring further.

<AgentInstructions>

## Submitting Feedback

If you encounter incorrect, outdated, or confusing documentation on this page, submit feedback:

POST https://docs.ton.org/feedback

```json
{
  "path": "/ecosystem/subsecond",
  "feedback": "Description of the issue"
}
```

Only submit feedback when you have something specific and actionable to report.

</AgentInstructions>

# How to adopt sub-second finality

export const Aside = ({type = "note", title = "", icon = "", iconType = "regular", children}) => {
  const asideVariants = ["note", "tip", "caution", "danger"];
  const asideComponents = {
    note: {
      outerStyle: "border-sky-500/20 bg-sky-50/50 dark:border-sky-500/30 dark:bg-sky-500/10",
      innerStyle: "text-sky-900 dark:text-sky-200",
      calloutType: "note",
      icon: <svg width="14" height="14" viewBox="0 0 14 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="w-4 h-4 text-sky-500" aria-label="Note">
          <path fill-rule="evenodd" clip-rule="evenodd" d="M7 1.3C10.14 1.3 12.7 3.86 12.7 7C12.7 10.14 10.14 12.7 7 12.7C5.48908 12.6974 4.0408 12.096 2.97241 11.0276C1.90403 9.9592 1.30264 8.51092 1.3 7C1.3 3.86 3.86 1.3 7 1.3ZM7 0C3.14 0 0 3.14 0 7C0 10.86 3.14 14 7 14C10.86 14 14 10.86 14 7C14 3.14 10.86 0 7 0ZM8 3H6V8H8V3ZM8 9H6V11H8V9Z"></path>
        </svg>
    },
    tip: {
      outerStyle: "border-emerald-500/20 bg-emerald-50/50 dark:border-emerald-500/30 dark:bg-emerald-500/10",
      innerStyle: "text-emerald-900 dark:text-emerald-200",
      calloutType: "tip",
      icon: <svg width="11" height="14" viewBox="0 0 11 14" fill="currentColor" xmlns="http://www.w3.org/2000/svg" className="text-emerald-600 dark:text-emerald-400/80 w-3.5 h-auto" aria-label="Tip">
          <path d="M3.12794 12.4232C3.12794 12.5954 3.1776 12.7634 3.27244 12.907L3.74114 13.6095C3.88471 13.8248 4.21067 14 4.46964 14H6.15606C6.41415 14 6.74017 13.825 6.88373 13.6095L7.3508 12.9073C7.43114 12.7859 7.49705 12.569 7.49705 12.4232L7.50055 11.3513H3.12521L3.12794 12.4232ZM5.31288 0C2.52414 0.00875889 0.5 2.26889 0.5 4.78826C0.5 6.00188 0.949566 7.10829 1.69119 7.95492C2.14321 8.47011 2.84901 9.54727 3.11919 10.4557C3.12005 10.4625 3.12175 10.4698 3.12261 10.4771H7.50342C7.50427 10.4698 7.50598 10.463 7.50684 10.4557C7.77688 9.54727 8.48281 8.47011 8.93484 7.95492C9.67728 7.13181 10.1258 6.02703 10.1258 4.78826C10.1258 2.15486 7.9709 0.000106649 5.31288 0ZM7.94902 7.11267C7.52078 7.60079 6.99082 8.37878 6.6077 9.18794H4.02051C3.63739 8.37878 3.10743 7.60079 2.67947 7.11294C2.11997 6.47551 1.8126 5.63599 1.8126 4.78826C1.8126 3.09829 3.12794 1.31944 5.28827 1.3126C7.2435 1.3126 8.81315 2.88226 8.81315 4.78826C8.81315 5.63599 8.50688 6.47551 7.94902 7.11267ZM4.87534 2.18767C3.66939 2.18767 2.68767 3.16939 2.68767 4.37534C2.68767 4.61719 2.88336 4.81288 3.12521 4.81288C3.36705 4.81288 3.56274 4.61599 3.56274 4.37534C3.56274 3.6515 4.1515 3.06274 4.87534 3.06274C5.11719 3.06274 5.31288 2.86727 5.31288 2.62548C5.31288 2.38369 5.11599 2.18767 4.87534 2.18767Z"></path>
        </svg>
    },
    caution: {
      outerStyle: "border-amber-500/20 bg-amber-50/50 dark:border-amber-500/30 dark:bg-amber-500/10",
      innerStyle: "text-amber-900 dark:text-amber-200",
      calloutType: "warning",
      icon: <svg className="flex-none w-5 h-5 text-amber-400 dark:text-amber-300/80" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2" aria-label="Warning">
          <path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
        </svg>
    },
    danger: {
      outerStyle: "border-red-500/20 bg-red-50/50 dark:border-red-500/30 dark:bg-red-500/10",
      innerStyle: "text-red-900 dark:text-red-200",
      calloutType: "danger",
      icon: <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" fill="currentColor" className="text-red-600 dark:text-red-400/80 w-4 h-4" aria-label="Danger">
          <path d="M17.1 292c-12.9-22.3-12.9-49.7 0-72L105.4 67.1c12.9-22.3 36.6-36 62.4-36l176.6 0c25.7 0 49.5 13.7 62.4 36L494.9 220c12.9 22.3 12.9 49.7 0 72L406.6 444.9c-12.9 22.3-36.6 36-62.4 36l-176.6 0c-25.7 0-49.5-13.7-62.4-36L17.1 292zm41.6-48c-4.3 7.4-4.3 16.6 0 24l88.3 152.9c4.3 7.4 12.2 12 20.8 12l176.6 0c8.6 0 16.5-4.6 20.8-12L453.4 268c4.3-7.4 4.3-16.6 0-24L365.1 91.1c-4.3-7.4-12.2-12-20.8-12l-176.6 0c-8.6 0-16.5 4.6-20.8 12L58.6 244zM256 128c13.3 0 24 10.7 24 24l0 112c0 13.3-10.7 24-24 24s-24-10.7-24-24l0-112c0-13.3 10.7-24 24-24zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"></path>
        </svg>
    }
  };
  let variant = type;
  let gotInvalidVariant = false;
  if (!asideVariants.includes(type)) {
    gotInvalidVariant = true;
    variant = "danger";
  }
  const iconVariants = ["regular", "solid", "light", "thin", "sharp-solid", "duotone", "brands"];
  if (!iconVariants.includes(iconType)) {
    iconType = "regular";
  }
  return <>
      <div className={`callout my-4 px-5 py-4 overflow-hidden rounded-2xl flex gap-3 border ${asideComponents[variant].outerStyle}`} data-callout-type={asideComponents[variant].calloutType}>
        <div className="mt-0.5 w-4" data-component-part="callout-icon">
          {}
          {icon === "" ? asideComponents[variant].icon : <Icon icon={icon} iconType={iconType} size={14} />}
        </div>
        <div className={`text-sm prose min-w-0 w-full ${asideComponents[variant].innerStyle}`} data-component-part="callout-content">
          {gotInvalidVariant ? <p>
              <span className="font-bold">
                Invalid <code>type</code> passed!
              </span>
              <br />
              <span className="font-bold">Received: </span>
              {type}
              <br />
              <span className="font-bold">Expected one of: </span>
              {asideVariants.join(", ")}
            </p> : <>
              {title && <p className="font-bold">{title}</p>}
              {children}
            </>}
        </div>
      </div>
    </>;
};

The TON Core team has [released Catchain 2.0](https://t.me/toncore/104) on mainnet. This consensus upgrade enables sub-second block finality, reducing the block interval from about 2.5s to about 400ms.

However, faster block production does not automatically reduce end-to-end latency for users. Projects must adapt their applications so transaction status updates and UI changes use the new timing guarantees.

## Current status

<Aside type="note">Sub-second finality is live on TON mainnet.</Aside>

As of April 9th 2026, mainnet runs with a block interval of about 400 ms instead of \~2.5 s before the upgrade, producing roughly 6.25x more blocks per second. Target finalization lag is reduced from \~10 s to about 1 s.

| Network                      | Block interval | Blocks per second | Finalization lag |
| ---------------------------- | -------------- | ----------------- | ---------------- |
| Mainnet                      | \~400ms        | \~2.5             | \~1s             |
| Testnet                      | \~450ms        | \~2.2             | \~1–2s           |
| Mainnet before Apr 9th, 2026 | \~2.5s         | \~0.4             | \~10s            |

* Together with the consensus update, the [Streaming API v2](#ton-center-streaming-api-v2) delivers status updates with 30 to 100ms latency.
* Testnet remains the primary environment for project testing.

## Example of sub-second user experience in action

<video autoPlay muted loop src="https://mintcdn.com/companyname-a7d5b98e/Ak--BzBKYJsN0HjF/resources/videos/subsecond-example.mov?fit=max&auto=format&n=Ak--BzBKYJsN0HjF&q=85&s=cc79d8ac0165843cd1d21aef333fe5fe" alt="Example of sub-second user experience" data-path="resources/videos/subsecond-example.mov" />

[MyTonWallet](https://mytonwallet.io/) and [tonscan.org](https://tonscan.org) already use Streaming API v2 on both mainnet and testnet to deliver transaction status updates with low latency. These projects have nearly halved interface delays, and the mainnet upgrade will further reduce them.

## What projects need to do

### Wallets and dApps

A faster chain alone does not reduce end-to-end latency if the application continues to use HTTP polling. In this case, transaction status updates can still arrive 10 seconds or more after inclusion. To support sub-second latency, deliver transaction updates through streaming APIs instead of polling.

#### Actions

* Switch to a streaming API such as [TON Center Streaming API v2](#ton-center-streaming-api-v2) or [TonAPI Streaming API](#tonapi-streaming-api).
  Handle all four transaction statuses: `"pending"`, `"confirmed"`, `"finalized"`, and `"trace_invalidated"`.

* If Streaming API cannot be used, reduce polling intervals and adjust assumptions about transaction timing.
  Interfaces should be designed to expect results in under 1 second.

### Self-hosted nodes, liteservers, and TON Center instances

#### Actions

1. Update all self-hosted components to the versions that include Catchain 2.0 support:

   * TON node and liteserver – update to a release that supports the live mainnet consensus.
   * Self-hosted TON Center – update to a version with Streaming API v2 support.

2. After updating, verify each component on testnet and confirm that it operates correctly under the higher block rate. If any component still runs a pre-upgrade version, update it before relying on it in production.

### Indexers

Indexers must process about 6.25x more blocks per second without accumulating lag. If an indexer was tuned for 2.5s block intervals, it can fall behind under 400ms intervals.

#### Actions

1. Connect the indexer to testnet.

2. Run for 30 or more minutes.

3. Measure lag continuously.

4. If lag increases, identify and resolve bottlenecks such as database writes, network latency, and parsing throughput.

5. Generate the typical mainnet load profile on testnet and verify that the indexer keeps up.
   See [Expected user experience](#expected-user-experience) and [Test on testnet](#test-on-testnet) for guidance.

## Expected user experience

### Behavior without Streaming APIs

Even with blocks produced about 6.25x faster, applications that do not use the Streaming API would still:

* Poll HTTP endpoints at fixed intervals.
* Wait for full block finalization before updating the UI.
* Show delays of 10+ seconds to users.

A typical sequence for polling-based integrations:

1. 0s – user clicks "Send";
2. \~0.4s – transaction included in a shard block;
3. \~0.8s – shard block committed to masterchain;
4. \~10s – UI updates on the next HTTP polling request.

User perception: "You said the blockchain is fast. Why does my transfer still take 10 seconds?". In this model, the blockchain is fast, but the user interface still appears slow.

### Behavior with Streaming APIs

1. 0s – user clicks "Send";
2. \~0.1s – `"pending"` status with expected outcome is displayed;
3. \~0.4s – transaction included in a shard block and `"confirmed"` status is displayed;
4. \~0.8s – shard block committed to masterchain and `"finalized"` status is displayed.

<Aside type="caution">
  If the interface does not update quickly, users will not notice any improvement despite the blockchain upgrade.
</Aside>

### Why this matters

The sub-second finality upgrade is enabled on mainnet, but coordinated ecosystem changes are still required:

* TON Core delivers faster block production and low-latency APIs.
* Ecosystem projects must adapt indexers and UI layers to surface this speed.

If applications do not adapt, the upgrade will not become apparent. Projects that have adapted will showcase the intended behavior and user experience.

## How to integrate

### Recommended stack

For projects building on TON:

* Streaming API: [TON Center](#ton-center-streaming-api-v2) or [TonAPI](#tonapi-streaming-api).
* Data layer: [TON Center API v3](/ecosystem/api/toncenter/v3/overview) or TonAPI v2.
* SDK: [AppKit][appkit] for balances, tokens, NFTs, and contract interactions.
* Finality: wait for `"finalized"` in critical flows.

### Public liteserver

Public liteservers are available for both mainnet and testnet. Use global config files to discover and connect to them:

* Mainnet: [`ton.org/global.config.json`](https://ton.org/global.config.json)
* Testnet: [`ton.org/testnet-global.config.json`](https://ton.org/testnet-global.config.json)

<Aside type="caution">
  Public liteservers are suitable for testing only. Use private liteservers in production.
</Aside>

### Self-hosted liteserver

If a liteserver node is self-hosted, ensure it is updated before mainnet rollout.

#### Actions

Confirm that the node version supports the new consensus.

### TON Center Streaming API v2

TON Center [Streaming API v2][streaming] provides:

* Push-based delivery of transaction status updates.
* Four statuses: `"pending"`, `"confirmed"`, `"finalized"`, `"trace_invalidated"`.
* Latency: 30–100ms from chain event to the client.

#### API token

* For testing purposes, any valid token for TON Center allows for 2 concurrent streaming connections.
* For production usage, higher connection limits require a paid plan.

#### Endpoints

SSE and WebSocket are available. Choose based on the stack:

* SSE – browser-friendly, server-to-client only (unidirectional).
* WebSocket – bidirectional, allows dynamic subscribe and unsubscribe after connection.

| Protocol  | Testnet URL                                          | Mainnet URL                                  |
| --------- | ---------------------------------------------------- | -------------------------------------------- |
| SSE       | `https://testnet.toncenter.com/api/streaming/v2/sse` | `https://toncenter.com/api/streaming/v2/sse` |
| WebSocket | `wss://testnet.toncenter.com/api/streaming/v2/ws`    | `wss://toncenter.com/api/streaming/v2/ws`    |

<Aside type="note">
  TonAPI also exposes Streaming API endpoints with the same SSE and WebSocket interface. Use the TON Center's [Streaming API v2 documentation][streaming] as the protocol reference.

  | Protocol  | Testnet URL                                  | Mainnet URL                          |
  | --------- | -------------------------------------------- | ------------------------------------ |
  | SSE       | `https://testnet.tonapi.io/streaming/v2/sse` | `https://tonapi.io/streaming/v2/sse` |
  | WebSocket | `wss://testnet.tonapi.io/streaming/v2/ws`    | `wss://tonapi.io/streaming/v2/ws`    |

  Authentication uses a [Ton Console API key](https://tonconsole.com/tonapi/api-keys).
</Aside>

<Aside type="caution" title={"SSE known limitations"}>
  1. Rate limit on reconnect (429 error).

     If a client reconnects immediately after a disconnect, the previous connection may still be open for \~1 minute. The reconnect attempt receives a 429 error. Use exponential backoff or an enterprise API key.

  2. POST-only subscription.

     Despite SSE typically using `GET`, this endpoint requires a `POST` with the subscription JSON in the request body. `GET` is not supported yet.

  3. No invalidation signal for `account_state_change` / `jettons_change`.

     If a `confirmed` account state or jetton balance update is later rolled back, no `"trace_invalidated"` notification is sent for these event types. Teams using `account_state_change` or `jettons_change` at `"confirmed"` finality should be aware of this gap and consider waiting for `"finalized"` for balance-critical flows.
</Aside>

#### Transaction status flow to implement

1. Initiate the transaction after the user's request.
2. Subscribe to the sender or recipient address through the Streaming API before or immediately after sending.

   * On `pending`, display a processing indicator.
   * On `confirmed`, optionally display optimistic success.
   * On `finalized`, display confirmed success and update state.
   * On `trace_invalidated`, discard a cached trace and recheck the status manually.

#### Configure `min_finality`

The `min_finality` parameter controls the earliest status delivered. The default value is `"finalized"`.

If the parameter is omitted, only `"finalized"` events are delivered. `"pending"` and `"confirmed"` updates are not sent.

| Use case                       | `min_finality` value                          |
| ------------------------------ | --------------------------------------------- |
| Send flow (real-time feedback) | `"pending"` to receive four status updates.   |
| History and balance display    | `"finalized"` to work only with settled data. |

Example subscription (send flow):

```json theme={"theme":{"light":"github-light-default","dark":"dark-plus"},"languages":{"custom":["/resources/grammars/tolk.tmLanguage.json","/resources/grammars/tlb.tmLanguage.json","/resources/grammars/fift.tmLanguage.json","/resources/grammars/tasm.tmLanguage.json","/resources/grammars/func.tmLanguage.json"]}}
{
  "accounts": ["<ADDRESS>"],
  "min_finality": "pending"
}
```

#### WebSocket keepalive

* Send a `ping` every 15 seconds to keep the connection alive.
* SSE connections receive automatic server-side keepalive (`: keepalive`) every 15 seconds; no client action required.

### TonAPI Streaming API

TonAPI Streaming API's interface is fully compatible and can be used interchangeably with TON Center's [Streaming API v2][streaming].

### AppKit for app developers

[AppKit][appkit] provides ready-to-use components for frontend applications. It handles out of the box:

* TON balance for any address;
* Jetton balances and metadata;
* NFT holdings;
* Contract state reads;
* Transaction sending, including jetton transfers.

## Test on testnet

Testnet runs at sub-second block generation speed. Use it for testing projects before shipping production changes on mainnet.

### Testnet endpoints

Use the [public API endpoints overview](/ecosystem/api/overview) for testnet endpoints, including TON Center and TonAPI streaming endpoints.

### How to get test tokens

* For the standard faucet, up to 2 TON per hour, [use Telegram Testgiver TON bot](/ecosystem/wallet-apps/get-coins#how-to-get-coins-on-testnet).
* For larger allocations up to 5,000 TON, [use the request form](/ecosystem/wallet-apps/get-coins#use-request-form).

### What to test

Perform the following tests to validate UX and wallet behavior.

#### For indexer teams

1. Connect indexer to testnet.
2. Run for 30+ minutes under normal conditions.
3. Measure indexer lag as the time between block production and indexer processing.
4. Ensure lag remains below 500ms and no backlog accumulates.

#### For UX and app teams

1. Connect to testnet endpoints.
2. Initiate a TON transfer.
3. Observe three statuses in sequence: `"pending"` → `"confirmed"` → `"finalized"`.
4. Measure time from transaction send to `"finalized"`. It should be under 1 second on testnet.
5. Test `"trace_invalidated"` path: intentionally send a malformed transaction and confirm that UI handles it correctly.

#### For wallet teams

1. Verify balance updates reflect within 1 second of `"finalized"` status.
2. Verify transaction history updates in real time.

## Resources

* [Announcement, Telegram channel](https://t.me/toncoin/2304)
* [TON Core deployment progress, Telegram channel](https://t.me/toncore/99)
* [TON Core R\&D technical overview, Telegram channel](https://t.me/toncore/98)
* [UX approaches for sub-second finality, Telegraph](https://telegra.ph/New-Approaches-to-Blockchain-User-Experience-08-02)
* [TON Center Streaming API v2][streaming]
* [API overview and public endpoints](/ecosystem/api/overview)
* [AppKit documentation][appkit]

## Get support

Use the [sub-second finality support chat](https://t.me/subsecond_upgrade) for questions about this upgrade.

[appkit]: /ecosystem/appkit/overview

[streaming]: /ecosystem/api/toncenter/streaming/overview
