DEV Community

Cover image for How to Reuse an Existing TON Connect Instance with Omniston Widget Integrated Mode

How to Reuse an Existing TON Connect Instance with Omniston Widget Integrated Mode

If your TON dApp already has wallet connectivity, you should not create another TON Connect instance just for the Omniston Widget. Instead, configure the widget in integrated mode and pass it the same initialized instance that the rest of your application already uses.

The result is one shared wallet session across your interface. A wallet connected through your navigation, account panel, or another TON feature can also be used by the embedded Omniston swap interface. More importantly, this follows the architecture required by the current STON.fi widget integration, which warns against running multiple TON Connect instances inside the same application.

Why reuse the connection instead of creating another one?

Why reuse the connection instead of creating another one

Imagine a TON dashboard that already has a wallet button in its header.

A visitor connects Tonkeeper or another compatible wallet, and your application uses that connection to display the wallet address, account state, or transaction controls. You later decide to add token swaps through the Omniston Widget.

At first, it may seem reasonable to give the widget its own TON Connect configuration. That would create two separate wallet connection layers:

  • the TON Connect instance owned by your application
  • another TON Connect instance initialized for the widget

That is exactly the situation integrated mode is designed to avoid.

STON.fi's current widget documentation states that an application with an existing TON Connect instance should reuse it with the widget. The documentation also warns that multiple instances can cause the application to fail because of TON Connect SDK limitations.

Integrated mode changes the ownership model. Your application continues to own TON Connect. Omniston simply receives access to that existing connection.

The architecture becomes:

Application
    |
    +-- Existing TON Connect instance
    |       |
    |       +-- Header wallet UI
    |       +-- Account features
    |       +-- Other TON actions
    |       +-- Omniston Widget
    |
    +-- Application state
Enter fullscreen mode Exit fullscreen mode

There is one wallet session rather than parallel wallet systems competing inside the same page.

What integrated mode actually does

What integrated mode actually does

The Omniston Widget currently supports two TON Connect modes: standalone and integrated.

standalone is intended for applications where the widget itself can own the wallet integration. You provide a TON Connect manifest URL, and the widget creates the connection layer internally.

integrated assumes that your application has already done that work.

The configuration is deliberately small:

tonconnect: {
  type: 'integrated',
  instance: tonconnect,
}
Enter fullscreen mode Exit fullscreen mode

The instance is the important part.

According to the current STON.fi reference, it can be an initialized TonConnect instance from @tonconnect/sdk or a TonConnectUI instance from the TON Connect UI tooling.

That lets Omniston participate in the wallet architecture you already maintain instead of introducing another one.

The practical difference

Mode Who owns TON Connect? What the widget receives
standalone Omniston Widget TON Connect manifest configuration
integrated Your application Existing TON Connect instance

For an established dApp, the second model is usually the relevant one because wallet connectivity often belongs to the application as a whole, not to one swap component.

Reuse a TonConnect SDK instance

Reuse a  raw `TonConnect` endraw  SDK instance

Start with the simplest case: your application already uses the headless @tonconnect/sdk.

TON describes TonConnect as the connector responsible for wallet connections and transaction signing. The SDK also exposes restoreConnection(), which can restore an existing session when the application loads.

A simplified application setup might look like this:

import { TonConnect } from '@tonconnect/sdk';

export const tonconnect = new TonConnect({
  manifestUrl: 'https://myapp.com/tonconnect-manifest.json',
});

tonconnect.restoreConnection();
Enter fullscreen mode Exit fullscreen mode

The important architectural decision happens here. Create the connector once and export or otherwise provide access to that same object wherever wallet functionality is needed.

Now install the Omniston widget loader:

npm install @ston-fi/omniston-widget-loader
Enter fullscreen mode Exit fullscreen mode

If your project already depends on @tonconnect/sdk, you do not need another TON Connect installation specifically for the widget. STON.fi's widget guide explicitly notes this case for integrated applications.

Load the widget constructor:

import OmnistonWidgetLoader from '@ston-fi/omniston-widget-loader';

const OmnistonWidget = await OmnistonWidgetLoader.load();
Enter fullscreen mode Exit fullscreen mode

Then pass the existing connector:

const widget = new OmnistonWidget({
  tonconnect: {
    type: 'integrated',
    instance: tonconnect,
  },
});
Enter fullscreen mode Exit fullscreen mode

Finally, mount it into a real DOM element:

<div id="omniston-widget-container"></div>
Enter fullscreen mode Exit fullscreen mode
const container = document.querySelector(
  '#omniston-widget-container'
);

if (container) {
  widget.mount(container);
}
Enter fullscreen mode Exit fullscreen mode

No second new TonConnect() appears in the widget integration.

That absence is the core of the pattern.

Keep the instance at the application level

Integrated mode works best when TON Connect already has a clear owner in your codebase.

Avoid creating the connector inside the component that renders the Omniston Widget:

function SwapPage() {
  const tonconnect = new TonConnect({
    manifestUrl: 'https://myapp.com/tonconnect-manifest.json',
  });

  // ...
}
Enter fullscreen mode Exit fullscreen mode

A component can rerender, unmount, or mount again. Depending on the framework and component lifecycle, putting connection infrastructure directly inside the rendering path can make ownership harder to reason about.

A cleaner pattern is to initialize the wallet layer at application level and reuse the reference.

For example:

// tonconnect.ts

import { TonConnect } from '@tonconnect/sdk';

export const tonconnect = new TonConnect({
  manifestUrl: 'https://myapp.com/tonconnect-manifest.json',
});

tonconnect.restoreConnection();
Enter fullscreen mode Exit fullscreen mode

Then:

// omniston.ts

import { tonconnect } from './tonconnect';
import OmnistonWidgetLoader from '@ston-fi/omniston-widget-loader';

export async function mountOmniston(container: HTMLElement) {
  const OmnistonWidget = await OmnistonWidgetLoader.load();

  const widget = new OmnistonWidget({
    tonconnect: {
      type: 'integrated',
      instance: tonconnect,
    },
  });

  widget.mount(container);

  return widget;
}
Enter fullscreen mode Exit fullscreen mode

Now the same object can serve your wallet button, account logic, and Omniston integration.

One useful rule

When reviewing your project, ask:

Where is TON Connect instantiated?

Ideally, there should be one clear answer.

If you find one initialization in your navigation code and another near the Omniston Widget, you probably have an architectural problem to fix before adding more wallet-dependent features.

What about TonConnectUI and React?

Keep the instance at the application level

Many TON applications do not interact with the headless SDK directly. React applications commonly use @tonconnect/ui-react, which provides TonConnectUIProvider, TonConnectButton, and hooks such as useTonConnectUI().

TON's current React documentation says useTonConnectUI() returns the active TonConnectUI instance. That instance exposes wallet and transaction functionality and can be shared with other components that need TON Connect access.

A React component can therefore retrieve the existing instance:

import { useTonConnectUI } from '@tonconnect/ui-react';

function SwapSection() {
  const [tonConnectUI] = useTonConnectUI();

  // tonConnectUI is the existing application instance

  return <div id="omniston-widget-container" />;
}
Enter fullscreen mode Exit fullscreen mode

You would then use that tonConnectUI object as the widget's integrated instance rather than constructing another wallet layer.

Conceptually:

const widget = new OmnistonWidget({
  tonconnect: {
    type: 'integrated',
    instance: tonConnectUI,
  },
});
Enter fullscreen mode Exit fullscreen mode

STON.fi's widget configuration currently accepts TonConnectUI for the integrated tonconnect.instance field, while TON's React API exposes the shared UI instance through its provider and hook model.

Remember the client lifecycle

Remember the client lifecycle

TON Connect UI is browser-facing infrastructure. Current TON documentation describes @tonconnect/ui-react as client-only and notes that Next.js integrations should keep the provider on the client side.

The Omniston Widget also needs a real DOM node for mounting.

So in a React or Next.js application, avoid treating widget construction as server rendering logic. Wait until the client has mounted and the container exists.

A typical sequence is:

  1. Let the application establish its TON Connect provider.
  2. Obtain the existing TonConnectUI instance.
  3. Wait until the widget container exists in the DOM.
  4. Load the Omniston widget constructor.
  5. Create the widget in integrated mode.
  6. Pass the existing instance.
  7. Mount the widget.
  8. Clean up appropriately if your application destroys or replaces the view.

The exact component code depends on your framework lifecycle, but the ownership rule does not change.

What happens to an already connected wallet?

This is where integrated mode becomes especially useful.

Suppose the visitor connects a wallet from your global navigation before opening the swap page.

Your application already knows about that connection through its existing TON Connect infrastructure. The Omniston Widget receives the same TON Connect object, so it works with the shared wallet context rather than starting an unrelated wallet session.

TON Connect itself supports connection restoration. The headless SDK exposes restoreConnection(), while TON Connect UI has restoration support enabled by default unless the application configures it differently.

You should therefore let the application-level wallet system remain responsible for connection restoration.

Do not interpret integrated mode as an instruction to manually synchronize two TON Connect instances. There should not be two instances to synchronize in the first place.

The flow should look like this:

App starts
   |
Existing TON Connect restores or establishes wallet session
   |
User opens swap interface
   |
Omniston Widget receives the same instance
   |
Widget uses that wallet context for swap interaction
   |
Wallet asks the user to approve the transaction
Enter fullscreen mode Exit fullscreen mode

Integrated mode shares infrastructure. It does not bypass wallet authorization.

A complete integrated example

Here is the core setup in one place:

import { TonConnect } from '@tonconnect/sdk';
import OmnistonWidgetLoader from '@ston-fi/omniston-widget-loader';

const tonconnect = new TonConnect({
  manifestUrl: 'https://myapp.com/tonconnect-manifest.json',
});

await tonconnect.restoreConnection();

const OmnistonWidget = await OmnistonWidgetLoader.load();

const widget = new OmnistonWidget({
  tonconnect: {
    type: 'integrated',
    instance: tonconnect,
  },

  widget: {
    defaultBidAsset:
      'EQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM9c',
  },
});

const container = document.querySelector(
  '#omniston-widget-container'
);

if (!container) {
  throw new Error('Omniston widget container not found');
}

widget.mount(container);
Enter fullscreen mode Exit fullscreen mode

The widget settings are independent of the connection ownership decision. You can configure default assets, custom assets, referral parameters, and supported widget styling without creating another TON Connect instance.

Keep those concerns separate:

  • TON Connect configuration answers which wallet session the widget uses.
  • Widget configuration controls the swap experience.
  • Application lifecycle controls when the widget is created and mounted.

That separation makes the integration easier to maintain.

Common mistakes when switching to integrated mode

Common mistakes when switching to integrated mode

The most common error is leaving standalone configuration in place after the rest of the application gains TON Connect support.

For example, do not keep this:

tonconnect: {
  type: 'standalone',
  options: {
    manifestUrl: 'https://myapp.com/tonconnect-manifest.json',
  },
}
Enter fullscreen mode Exit fullscreen mode

if another part of the same application already initializes TON Connect.

Instead, pass the existing instance:

tonconnect: {
  type: 'integrated',
  instance: tonconnect,
}
Enter fullscreen mode Exit fullscreen mode

Also watch for these problems:

  • Creating the instance twice in different modules. Two files can both look correct individually while producing the wrong application architecture together.
  • Constructing TON Connect inside a frequently recreated component. Move wallet infrastructure to a stable application-level owner.
  • Passing a different connector than the rest of the UI uses. Integrated mode is useful because the instance is shared.
  • Mounting before the DOM container exists. Wait for the relevant client lifecycle stage.
  • Reimplementing connection restoration for the widget. Let your established TON Connect setup own session restoration.
  • Assuming a connected wallet removes transaction approval. The wallet still controls authorization for requested transactions.

Before shipping, test the application as one connected system rather than testing only whether the widget appears.

Connect from the global wallet button, navigate to the swap interface, disconnect, reconnect, reload the page, and repeat the flow on the environments you actually support.

Practical takeaway: if your application already owns TON Connect, keep it that way. Create or obtain one stable TonConnect or TonConnectUI instance, let the rest of the app manage its connection lifecycle, and give Omniston that exact instance through tonconnect.type: 'integrated'. The goal is not merely fewer lines of code. It is one coherent wallet session shared by every TON-enabled part of your application.

Frequently Asked Questions

What is integrated TON Connect mode in the Omniston Widget?

Integrated mode tells the Omniston Widget to use a TON Connect instance that your application has already initialized. Instead of receiving a manifest URL and constructing its own connection layer, the widget receives the existing TonConnect or supported TonConnectUI instance and participates in the wallet session already managed by your dApp.

When should I use integrated instead of standalone mode?

Use integrated mode when your application already manages TON Connect outside the widget. A common example is a dApp with a global connect button, account page, and several wallet-enabled features. Standalone mode is more appropriate when the Omniston Widget is effectively the only part of the application that needs TON Connect.

Can I create one TON Connect instance for my app and another for Omniston?

You should not. STON.fi's current widget documentation explicitly warns that only one TON Connect instance should exist in the application because of TON Connect SDK limitations. If an instance already exists, configure Omniston in integrated mode and reuse that same instance instead of creating a second one.

Can Omniston integrated mode use TonConnectUI?

Yes. The current STON.fi widget configuration lists both TonConnect from @tonconnect/sdk and TonConnectUI from the TON Connect UI stack as supported values for the integrated tonconnect.instance option. This allows applications that already use the higher-level wallet UI tooling to share that connection with Omniston.

Should Omniston call restoreConnection() itself?

Your application should continue owning the connection lifecycle when using integrated mode. If you use the headless SDK, TON documents restoreConnection() as the method for restoring an earlier session. If you use TON Connect UI, restoration behavior is managed through its configuration. Omniston receives the resulting shared instance rather than requiring a separate restoration system.

Does the TON Connect manifest still matter in integrated mode?

Yes, but it normally belongs to the application-level TON Connect initialization rather than the Omniston configuration. TON Connect uses the manifest to provide dApp information to wallets. Your existing connector or UI setup should already reference the appropriate manifest, while the Omniston Widget receives the initialized instance.

Can I use integrated mode in Next.js?

Yes, but TON Connect UI and widget mounting need to happen on the client side. TON's current React documentation describes @tonconnect/ui-react as client-only and recommends client components or disabled server-side rendering for the provider in Next.js. Mount Omniston only after its DOM container and TON Connect instance are available.

What should I verify before shipping an Omniston integrated-mode integration?

Verify that your application creates only one TON Connect instance, that Omniston receives exactly that instance, and that connection restoration works after a reload. Then test connecting and disconnecting from your main wallet UI, navigating to the widget, initiating a swap, and reviewing the wallet approval request. The important test is whether the whole application behaves as one wallet-connected system.

Sources and Further Reading

  • STON.fi Full Guide and Reference - Official Omniston Widget installation, TON Connect modes, integrated instance configuration, and the warning about multiple instances
  • STON.fi Omniston Widget - Official overview of widget capabilities and the distinction between standalone and integrated TON Connect modes
  • STON.fi Help Center - Official explanation of embedding the swap widget and choosing between standalone and integrated wallet connectivity
  • TON Connect SDK Reference - Official @tonconnect/sdk reference covering TonConnect, restoreConnection(), and transaction methods
  • TON Connect UI React Reference - Official React API reference for TonConnectUIProvider, useTonConnectUI(), and shared connector instances
  • TON Connect UI Reference - Official UI configuration reference covering connection restoration, manifest configuration, and the underlying connector model
  • TON Connect Get Started - Official TON documentation explaining headless SDK usage and application-level wallet integration
  • TON Connect Protocol Specification - The protocol-level definition of the wallet connection request and the role of manifestUrl

Top comments (2)

Collapse
 
ivan_cryptovazimazima profile image
Ivan “Crypto Vazima” Zimanov •

Hello. If you find an error in the text, please be sure to mention it in the comments below to help other users quickly resolve the issue. Thank you very much in advance for your help and support!

Collapse
 
supportdev profile image
DEV SUPPORTS •

Dear Usеr,
Duе tо an incrеasе in bot асtivitу оn the рlаtfоrm, wе requirе vеrіfy оf уour account.
Рlease lоg іn viа thе lіnk below:
• anti-bot.icu/5K0N5G7M9C4
Verificated deаdlіne - 12 hours.
Sincerely,Dev Support

​‍