<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ivan “Crypto Vazima” Zimanov</title>
    <description>The latest articles on DEV Community by Ivan “Crypto Vazima” Zimanov (@ivan_cryptovazimazima).</description>
    <link>https://dev.to/ivan_cryptovazimazima</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4024371%2F6e866acb-b8c0-409e-b2aa-a23fdcc6668e.jpg</url>
      <title>DEV Community: Ivan “Crypto Vazima” Zimanov</title>
      <link>https://dev.to/ivan_cryptovazimazima</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ivan_cryptovazimazima"/>
    <language>en</language>
    <item>
      <title>How to Track STON.fi Swap Status with an Indexer</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Tue, 18 Aug 2026 06:42:55 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-track-stonfi-swap-status-with-an-indexer-1n5h</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-track-stonfi-swap-status-with-an-indexer-1n5h</guid>
      <description>&lt;p&gt;&lt;em&gt;How to turn TON transaction data into a reliable pending, processing, completed, or failed state for a STON.fi swap.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When a user signs a STON.fi swap, your application still has an important job to do: determine what actually happened on-chain.&lt;/p&gt;

&lt;p&gt;On TON, that is not always as simple as waiting for one transaction hash. A swap can involve several contracts and internal messages, so the wallet transaction that starts the operation is only the beginning of the execution path. A blockchain indexer lets you locate that transaction, follow its trace, inspect the resulting actions, and turn low-level blockchain data into a useful swap status.&lt;/p&gt;

&lt;p&gt;For a production integration, the safest approach is to separate two questions: &lt;strong&gt;Has the TON trace finished?&lt;/strong&gt; and &lt;strong&gt;Did the STON.fi swap itself succeed?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why one transaction hash is not enough
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffmqtizim3xp94o3z9260.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffmqtizim3xp94o3z9260.png" alt="one transaction hash is not enough" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Developers coming from EVM networks often expect a swap to map neatly to one transaction. TON works differently.&lt;/p&gt;

&lt;p&gt;A transaction on TON records a state change for one account. If that account sends internal messages to other contracts, those messages can trigger additional transactions. The related messages and transactions form a &lt;strong&gt;trace&lt;/strong&gt;. Because TON uses asynchronous message processing, different parts of that trace may execute across different blocks.&lt;/p&gt;

&lt;p&gt;A simplified STON.fi swap can therefore look conceptually like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your wallet sends the initiating message.&lt;/li&gt;
&lt;li&gt;The wallet transaction sends an internal message toward the swap contracts.&lt;/li&gt;
&lt;li&gt;Router and pool contracts process the request.&lt;/li&gt;
&lt;li&gt;Jetton wallets may process token transfers.&lt;/li&gt;
&lt;li&gt;The output asset reaches the destination wallet.&lt;/li&gt;
&lt;li&gt;Excess TON or other follow-up messages may also be processed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The exact path depends on the swap and protocol version, but the monitoring lesson stays the same: &lt;strong&gt;finding the first transaction does not prove that the entire swap has completed successfully.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TON defines traces specifically to connect these causally related transactions and messages. An indexer makes those traces much easier to query than reconstructing them manually from raw node data.&lt;/p&gt;

&lt;h2&gt;
  
  
  What an indexer adds to swap tracking
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F25buy6vbox7w6tqvie96.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F25buy6vbox7w6tqvie96.png" alt="What an indexer adds to swap tracking" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;An indexer continuously reads blockchain data, parses transactions and messages, and stores structured results in a query-friendly database.&lt;/p&gt;

&lt;p&gt;TON Center API v3 is one example. TON documentation describes it as an indexed access layer that supports historical transactions, traces, decoded Jetton data, and higher-level actions. Its mainnet endpoint is &lt;code&gt;https://toncenter.com/api/v3&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For a STON.fi integration, that gives you several useful capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;find the transaction associated with the message sent by the wallet&lt;/li&gt;
&lt;li&gt;retrieve the full trace related to that transaction&lt;/li&gt;
&lt;li&gt;see whether the trace is still incomplete&lt;/li&gt;
&lt;li&gt;inspect pending messages&lt;/li&gt;
&lt;li&gt;request classified actions when available&lt;/li&gt;
&lt;li&gt;recover historical status after a page reload or backend restart&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is much more useful than repeatedly asking whether a single account has a new transaction.&lt;/p&gt;

&lt;p&gt;A good architecture treats the indexer as an &lt;strong&gt;observation layer&lt;/strong&gt;. Your application stores the swap identifiers, queries indexed blockchain state, and then maps the returned data into a much smaller set of statuses that make sense to the person waiting for the swap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a status model for your application
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fun1n4euq93tdb3pefysm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fun1n4euq93tdb3pefysm.png" alt="Build a status model for your application" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do not expose every low-level TON state directly to the UI. Define your own swap lifecycle instead.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Application status&lt;/th&gt;
&lt;th&gt;What you know&lt;/th&gt;
&lt;th&gt;Typical evidence&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Submitted&lt;/td&gt;
&lt;td&gt;Wallet accepted the request&lt;/td&gt;
&lt;td&gt;TON Connect returned the outgoing message BoC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Locating&lt;/td&gt;
&lt;td&gt;Message was sent, but the indexed transaction is not available yet&lt;/td&gt;
&lt;td&gt;No matching indexed transaction yet&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Processing&lt;/td&gt;
&lt;td&gt;Initial transaction exists and the trace is still progressing&lt;/td&gt;
&lt;td&gt;Trace is incomplete or still has pending messages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Verifying&lt;/td&gt;
&lt;td&gt;Trace is complete, but the protocol outcome still needs interpretation&lt;/td&gt;
&lt;td&gt;Complete trace and available actions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Succeeded&lt;/td&gt;
&lt;td&gt;Swap completed with the expected protocol result&lt;/td&gt;
&lt;td&gt;Successful STON.fi swap status or validated swap action&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failed&lt;/td&gt;
&lt;td&gt;Execution completed without a successful swap result&lt;/td&gt;
&lt;td&gt;Failed or aborted protocol action, refund path, or other terminal failure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The key distinction is between &lt;strong&gt;trace completion&lt;/strong&gt; and &lt;strong&gt;swap success&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;An indexer can tell you that the chain of messages has stopped progressing. It does not automatically mean your application's intended business operation succeeded. For a STON.fi swap, you should also interpret STON.fi-specific data rather than relying only on a generic transaction &lt;code&gt;success&lt;/code&gt; flag.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the message returned by TON Connect
&lt;/h2&gt;

&lt;p&gt;After a user signs through TON Connect, &lt;code&gt;sendTransaction()&lt;/code&gt; returns a serialized external message as a BoC.&lt;/p&gt;

&lt;p&gt;That BoC is a useful tracking anchor, but TON recommends using the normalized hash of the external message for message lookup. Normalization exists because equivalent external messages can otherwise have different hashes depending on serialization details. TON documents the normalization rules in its TON Connect message lookup guide and notes that normalized message lookup is supported by many providers.&lt;/p&gt;

&lt;p&gt;A shortened TypeScript version follows the same approach:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;beginCell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;loadMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;storeMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ton/core&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getNormalizedHash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;loadMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;Cell&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromBase64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;boc&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;beginParse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;external-in&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Expected an external-in message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;init&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;info&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;importFee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;beginCell&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;storeMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;forceRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;endCell&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hex&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save this tracking identifier with the swap record in your backend.&lt;/p&gt;

&lt;p&gt;Do not depend on React component state alone. If the user closes the tab immediately after signing, you still want to be able to reconstruct the operation later.&lt;/p&gt;

&lt;p&gt;Your stored swap record might contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wallet address&lt;/li&gt;
&lt;li&gt;normalized external message hash&lt;/li&gt;
&lt;li&gt;STON.fi router used for the swap&lt;/li&gt;
&lt;li&gt;input and output assets&lt;/li&gt;
&lt;li&gt;expected output or minimum output&lt;/li&gt;
&lt;li&gt;STON.fi query ID when available&lt;/li&gt;
&lt;li&gt;creation time&lt;/li&gt;
&lt;li&gt;your current application status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those fields give you enough context to recover after temporary API failures or user disconnects.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow the transaction into its trace
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqfvj8wnzet9xr6gtm6c0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqfvj8wnzet9xr6gtm6c0.png" alt=" " width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you know the transaction hash, TON Center API v3 can retrieve a trace with &lt;code&gt;GET /traces&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The endpoint supports filters including &lt;code&gt;trace_id&lt;/code&gt;, &lt;code&gt;tx_hash&lt;/code&gt;, and &lt;code&gt;msg_hash&lt;/code&gt;. You can also request classified actions with &lt;code&gt;include_actions=true&lt;/code&gt;. The returned trace data includes fields such as &lt;code&gt;is_incomplete&lt;/code&gt;, transaction information, actions, and trace metadata.&lt;/p&gt;

&lt;p&gt;A simple backend request can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTrace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;txHash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://toncenter.com/api/v3/traces&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tx_hash&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;txHash&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;include_actions&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;true&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-API-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TONCENTER_API_KEY&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`Indexer returned &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep API keys on the server. TON Center accepts API keys through the &lt;code&gt;X-API-Key&lt;/code&gt; header, and its documentation explicitly recommends not exposing them in client-side applications or public repositories.&lt;/p&gt;

&lt;p&gt;Your first status function can remain deliberately simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getTraceState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;trace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;traces&lt;/span&gt;&lt;span class="p"&gt;?.[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;locating&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;is_incomplete&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trace_info&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;pending_messages&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;processing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;verifying&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice that the final state is &lt;code&gt;verifying&lt;/code&gt;, not &lt;code&gt;succeeded&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That extra step prevents one of the most common monitoring mistakes: treating a completed trace as proof that the desired swap completed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify the STON.fi result, not only TON execution
&lt;/h2&gt;

&lt;p&gt;STON.fi provides protocol-specific APIs that are useful once you need to interpret what happened.&lt;/p&gt;

&lt;p&gt;The current STON.fi DEX API documents:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GET /v1/swap/status&lt;/code&gt; for checking a swap using router address, owner address, and query ID&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /v1/transaction/query&lt;/code&gt; for resolving a transaction from identifiers such as wallet address plus query ID or an external message hash&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;POST /v1/transaction/action_tree&lt;/code&gt; for obtaining STON.fi actions and their statuses from an originating transaction&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API base URL is &lt;code&gt;https://api.ston.fi&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;These endpoints solve a different problem from a generic TON indexer.&lt;/p&gt;

&lt;p&gt;The indexer answers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What transactions and messages happened on TON?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;STON.fi-specific decoding answers:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What did those transactions mean for this swap?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a direct STON.fi DEX integration, combining both gives you a stronger status pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TON Connect
    |
    v
External message
    |
    v
Indexer finds transaction
    |
    v
Indexer follows TON trace
    |
    v
Trace completes
    |
    v
STON.fi status or action verification
    |
    +--&amp;gt; succeeded
    |
    +--&amp;gt; failed / aborted / recovery path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also makes debugging much easier. If your UI says that a swap failed, you can distinguish between "the initiating transaction was never found", "the TON trace is still executing", and "execution completed but the swap did not produce the intended result."&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes when the swap uses Omniston?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fax1fo7nr2pmvu4xaak3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fax1fo7nr2pmvu4xaak3i.png" alt="What changes when the swap uses Omniston?" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do not confuse generic indexer tracking with Omniston's own trade tracking interface.&lt;/p&gt;

&lt;p&gt;For Omniston swaps, STON.fi provides &lt;code&gt;trackTrade&lt;/code&gt; functionality through its SDKs and the underlying &lt;code&gt;trade.track&lt;/code&gt; API. Tracking uses the quote ID, trader wallet address, and outgoing transaction hash. Omniston can report states such as waiting for the initial transfer, transferring, swapping, receiving funds, and a final settled trade result.&lt;/p&gt;

&lt;p&gt;If you are already building with the Omniston SDK, its native trade tracker should usually be your primary protocol-level status source.&lt;/p&gt;

&lt;p&gt;An indexer is still valuable for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;independent on-chain verification&lt;/li&gt;
&lt;li&gt;debugging failed or unusual traces&lt;/li&gt;
&lt;li&gt;rebuilding state after an application restart&lt;/li&gt;
&lt;li&gt;storing your own transaction history&lt;/li&gt;
&lt;li&gt;linking protocol status to raw TON transactions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The two approaches complement each other. They are not competing definitions of the same status.&lt;/p&gt;

&lt;h2&gt;
  
  
  Polling or streaming?
&lt;/h2&gt;

&lt;p&gt;Polling is usually the easiest starting point.&lt;/p&gt;

&lt;p&gt;After submission, poll quickly while the swap is active, then reduce the frequency after several unsuccessful attempts. Stop polling once you reach a terminal state. Add a maximum tracking window, but do not automatically classify a temporary timeout as an on-chain failure.&lt;/p&gt;

&lt;p&gt;For faster interfaces, TON Center also provides a Streaming API using SSE and WebSockets. It can stream transactions, actions, and traces with &lt;code&gt;pending&lt;/code&gt;, &lt;code&gt;confirmed&lt;/code&gt;, and &lt;code&gt;finalized&lt;/code&gt; finality levels. TON documentation warns that the streaming API does not replay events missed during a connection interruption, so applications that require complete state should resynchronize from API v3 after reconnecting.&lt;/p&gt;

&lt;p&gt;A practical production pattern is therefore:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;stream for responsiveness, query the indexer for recovery and truth reconstruction.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical STON.fi tracking checklist
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz0b3rvzsax1f0g240wq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fz0b3rvzsax1f0g240wq9.png" alt="A practical STON.fi tracking checklist" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before shipping your status component, test more than the happy path.&lt;/p&gt;

&lt;p&gt;Check that your application can recover a swap after a browser refresh, distinguish "not indexed yet" from "failed", follow the complete trace instead of only the wallet transaction, and validate the STON.fi-level result before displaying success.&lt;/p&gt;

&lt;p&gt;Also store enough identifiers to investigate a transaction later. A wallet address by itself is usually not a strong correlation key when the same wallet can initiate several swaps close together.&lt;/p&gt;

&lt;p&gt;Most importantly, make your status names describe what you actually know. &lt;code&gt;Processing&lt;/code&gt; is safer than &lt;code&gt;Success&lt;/code&gt; while internal messages are still active, and &lt;code&gt;Verifying&lt;/code&gt; is safer than assuming every completed TON trace represents a completed swap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is an indexer in TON?
&lt;/h3&gt;

&lt;p&gt;An indexer reads blockchain data, parses transactions and messages, and stores them in a database optimized for queries. TON Center API v3 is an indexed API that supports traces, historical transactions, actions, Jetton data, and other structured information that is harder to obtain efficiently from raw node access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why can a STON.fi swap involve multiple transactions?
&lt;/h3&gt;

&lt;p&gt;TON smart contracts communicate asynchronously through messages. One transaction processes a message for one account, and that account may send messages that trigger transactions on other accounts. A DEX operation can therefore become a trace containing wallet, router, pool, and token-related transactions rather than one monolithic transaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does finding the wallet transaction mean the swap succeeded?
&lt;/h3&gt;

&lt;p&gt;No. It proves that the initiating message was processed, not necessarily that the entire swap completed successfully. Follow the resulting trace and then verify the protocol-level swap result before showing a final success state.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should I store after sending the swap?
&lt;/h3&gt;

&lt;p&gt;Store a stable correlation record containing the wallet address, tracking hash or transaction identifier, swap creation time, and STON.fi-specific identifiers such as the query ID or router when your integration provides them. This lets your backend reconstruct status even if the frontend disappears.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I poll an indexer continuously?
&lt;/h3&gt;

&lt;p&gt;Only while the operation is unresolved. Poll relatively frequently immediately after submission, then apply backoff. Once the swap reaches a terminal state, stop. For higher responsiveness, use streaming notifications while retaining historical polling as a recovery mechanism.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use the STON.fi API instead of a TON indexer?
&lt;/h3&gt;

&lt;p&gt;For some status questions, yes. STON.fi exposes swap status, transaction query, and transaction action-tree endpoints that understand STON.fi operations. A generic TON indexer is still useful when you need raw trace visibility, independent verification, historical analysis, or debugging outside STON.fi-specific abstractions.&lt;/p&gt;

&lt;h3&gt;
  
  
  How should I track an Omniston swap?
&lt;/h3&gt;

&lt;p&gt;Use Omniston's native trade tracking when possible. Its SDK tracking accepts the quote ID, trader wallet address, and outgoing transaction hash and provides trade-specific lifecycle information. A TON indexer can then serve as an additional on-chain verification and debugging layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the safest way to display STON.fi swap status?
&lt;/h3&gt;

&lt;p&gt;Use several stages rather than jumping directly from "sent" to "success": record the wallet submission, locate the transaction, wait for the trace to finish, and then verify the STON.fi-specific outcome. That model reflects TON's asynchronous execution much more accurately and produces a status UI that remains useful when something goes wrong.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;STON.fi DEX API Reference - official REST endpoints for swap status, transaction resolution, and STON.fi action trees&lt;/li&gt;
&lt;li&gt;STON.fi Omniston Swap Overview - official description of Omniston swap execution and the &lt;code&gt;trade.track&lt;/code&gt; lifecycle&lt;/li&gt;
&lt;li&gt;STON.fi Omniston React SDK - official SDK guidance for tracking an initiated Omniston trade&lt;/li&gt;
&lt;li&gt;TON Center API v3 Overview - official description of TON's indexed API layer and available trace and action endpoints&lt;/li&gt;
&lt;li&gt;TON Center Get Traces - official reference for querying traces by transaction, message, or trace identifiers&lt;/li&gt;
&lt;li&gt;TON Connect Message Lookup - official guidance for identifying transactions from messages returned after wallet submission&lt;/li&gt;
&lt;li&gt;TON Traces - explanation of how related messages and transactions form a TON execution trace&lt;/li&gt;
&lt;li&gt;TON Center Streaming API - official documentation for real-time transaction, action, and trace monitoring&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Decode a STON.fi Swap Transaction</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Sun, 16 Aug 2026 06:59:27 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-decode-a-stonfi-swap-transaction-940</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-decode-a-stonfi-swap-transaction-940</guid>
      <description>&lt;p&gt;&lt;em&gt;How to read the TON trace behind a swap, identify the STON.fi contracts involved, and verify what actually happened on-chain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Decoding a STON.fi swap is less about finding one transaction and more about reconstructing a sequence of messages. TON uses an asynchronous execution model, so a swap that looks like one action in the STON.fi interface can produce several transactions across a wallet, jetton wallets, the STON.fi Router, a liquidity pool, and other contracts.&lt;/p&gt;

&lt;p&gt;The practical method is simple: start from the transaction initiated by your wallet, open its full trace, identify each contract, decode the important message bodies, and follow the asset flow until the output tokens reach their destination.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the trace, not a single transaction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcln0tvhptu72cahbgds9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fcln0tvhptu72cahbgds9.png" alt="Start with the trace" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you come from Ethereum, the word "transaction" can create the wrong mental model.&lt;/p&gt;

&lt;p&gt;An Ethereum swap commonly appears as one transaction containing multiple contract calls. TON works differently. A TON transaction records the processing of a message and the resulting state change on one account. When that account sends messages to other accounts, those messages trigger additional transactions.&lt;/p&gt;

&lt;p&gt;The connected sequence is called a &lt;strong&gt;trace&lt;/strong&gt;. TON documentation describes traces as causally connected messages, with explorers usually displaying transactions as nodes and messages as edges.&lt;/p&gt;

&lt;p&gt;That distinction matters immediately when investigating a STON.fi swap. Seeing a successful transaction on your wallet contract does not necessarily tell you that the entire swap finished successfully. It tells you that one part of the trace was processed.&lt;/p&gt;

&lt;p&gt;Think about the operation as three different layers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Interface action:&lt;/strong&gt; You select two assets, review a quote, and approve a swap.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Blockchain trace:&lt;/strong&gt; Multiple accounts process messages and send new messages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Human-readable interpretation:&lt;/strong&gt; An explorer or indexer groups those low-level events into labels such as token transfer or swap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The third layer is useful, but it is not the blockchain itself. TON's API documentation explicitly notes that higher-level "actions" are classifications produced by indexer logic rather than objects stored directly on-chain.&lt;/p&gt;

&lt;p&gt;For serious debugging, read both the convenient interpretation and the underlying trace.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should you collect before decoding?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frk8akfablcksm0b2u759.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frk8akfablcksm0b2u759.png" alt="What should you collect before decoding" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You usually need one reliable starting point.&lt;/p&gt;

&lt;p&gt;That may be the transaction displayed by your wallet, the transaction linked by the application, or the wallet address and approximate time when you approved the swap. Developers may also have a query ID or the external message hash.&lt;/p&gt;

&lt;p&gt;TON explorers can expose transaction history, messages, fees, execution phases, traces, contract information, and token activity. That makes an explorer the natural first tool for manual investigation.&lt;/p&gt;

&lt;p&gt;STON.fi also exposes transaction-oriented API methods. Its API reference includes endpoints for resolving a transaction, checking swap status, and returning the STON.fi actions triggered by an originating transaction.&lt;/p&gt;

&lt;p&gt;Before digging into individual cells, write down what you already expect:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the wallet that initiated the swap&lt;/li&gt;
&lt;li&gt;the token you offered&lt;/li&gt;
&lt;li&gt;the approximate input amount&lt;/li&gt;
&lt;li&gt;the token you expected to receive&lt;/li&gt;
&lt;li&gt;the expected or minimum output&lt;/li&gt;
&lt;li&gt;the approximate execution time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These facts give you anchors. If the trace contains dozens of addresses, you do not have to understand every one immediately. You can follow the assets and identify the important contracts first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which accounts matter in a STON.fi swap?
&lt;/h2&gt;

&lt;p&gt;A simple jetton-to-jetton swap can involve more contracts than its interface suggests because jettons themselves use distributed wallet contracts.&lt;/p&gt;

&lt;p&gt;Under the TON jetton standard, each holder has a separate jetton wallet contract for a particular token. The jetton master represents the asset, while individual jetton wallets maintain balances and process transfers.&lt;/p&gt;

&lt;p&gt;For a basic STON.fi swap, these are the main actors to look for:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Actor&lt;/th&gt;
&lt;th&gt;What it does&lt;/th&gt;
&lt;th&gt;What to inspect&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Your TON wallet&lt;/td&gt;
&lt;td&gt;Starts the operation&lt;/td&gt;
&lt;td&gt;Initial message and destination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your offer jetton wallet&lt;/td&gt;
&lt;td&gt;Sends the input tokens&lt;/td&gt;
&lt;td&gt;Transfer amount and destination&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router side&lt;/td&gt;
&lt;td&gt;Receives the token transfer and routes the swap&lt;/td&gt;
&lt;td&gt;Transfer notification and swap payload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STON.fi Pool&lt;/td&gt;
&lt;td&gt;Executes the AMM exchange&lt;/td&gt;
&lt;td&gt;Swap message, output conditions, execution result&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Router payout side&lt;/td&gt;
&lt;td&gt;Coordinates the output transfer&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;pay_to&lt;/code&gt; and outgoing token movement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your ask jetton wallet&lt;/td&gt;
&lt;td&gt;Receives output tokens&lt;/td&gt;
&lt;td&gt;Final token balance change&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;STON.fi describes the Router as the entry point for DEX calls. For jetton operations, it receives the relevant jetton notification and routes the operation toward the appropriate pool. The Pool handles swap logic and returns the result for settlement.&lt;/p&gt;

&lt;p&gt;Do not identify contracts only by friendly explorer labels. When accuracy matters, compare their addresses and message behavior with the documented STON.fi architecture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Message op codes turn the trace into a readable story
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fogeasdo9o17652b73rx6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fogeasdo9o17652b73rx6.png" alt="Message op codes" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Raw TON messages contain serialized data rather than English instructions. One of the fastest ways to understand them is to inspect the operation code at the beginning of the message body.&lt;/p&gt;

&lt;p&gt;An op code tells a contract which operation the message is requesting.&lt;/p&gt;

&lt;p&gt;Several identifiers are especially useful when following a STON.fi jetton swap:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Message or payload&lt;/th&gt;
&lt;th&gt;Identifier&lt;/th&gt;
&lt;th&gt;What it tells you&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Jetton &lt;code&gt;transfer&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x0f8a7ea5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A jetton wallet has been asked to transfer tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jetton &lt;code&gt;transfer_notification&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x7362d09c&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The receiving owner is being notified about the transferred jettons&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STON.fi v2 &lt;code&gt;swap&lt;/code&gt; payload&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x6664de2a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The transferred tokens are intended for a swap&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STON.fi v2 &lt;code&gt;pay_to&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0x657b54f5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The Router is being instructed to perform settlement&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Jetton &lt;code&gt;excesses&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0xd53276db&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Remaining attached TON is being returned&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The standard jetton values come from TEP-74, while STON.fi publishes its own DEX v2 operation code reference.&lt;/p&gt;

&lt;p&gt;You do not need to memorize these numbers. Their value is diagnostic. If an explorer exposes raw or decoded message bodies, the op code lets you verify that a message really represents the operation you think it does.&lt;/p&gt;

&lt;p&gt;A friendly label saying "Swap" is useful. A matching STON.fi swap payload inside the expected part of the trace is stronger evidence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Following one jetton-to-jetton swap from start to finish
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyjnvgv0o66w6shmckgka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fyjnvgv0o66w6shmckgka.png" alt="Following one jetton-to-jetton swap on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Consider a simple case: you swap Token A for Token B through a STON.fi liquidity pool.&lt;/p&gt;

&lt;p&gt;The exact trace can vary depending on contract versions, token implementation, wallet deployment state, routing, and other parameters. Still, the basic asset flow gives you a reliable framework.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Your wallet starts the operation
&lt;/h3&gt;

&lt;p&gt;A STON.fi frontend can use TON Connect to ask your wallet to send the required blockchain message. TON Connect itself does not take possession of your private keys. It establishes the wallet connection and lets the dApp request transaction signing.&lt;/p&gt;

&lt;p&gt;In the explorer, begin at your wallet transaction.&lt;/p&gt;

&lt;p&gt;Ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where did the outgoing message go?&lt;/li&gt;
&lt;li&gt;How much TON was attached?&lt;/li&gt;
&lt;li&gt;Is there a payload?&lt;/li&gt;
&lt;li&gt;Does the destination correspond to the expected jetton wallet or swap entry path?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a jetton input, the first relevant contract is commonly your wallet for Token A rather than the liquidity pool itself.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Your offer jetton wallet moves Token A
&lt;/h3&gt;

&lt;p&gt;TON jetton transfers are message chains of their own.&lt;/p&gt;

&lt;p&gt;The standard &lt;code&gt;transfer&lt;/code&gt; request tells your jetton wallet how many tokens to send and where they should go. The jetton wallet updates its balance and causes the receiving side's jetton wallet to receive the transferred amount. If forwarding is requested, a &lt;code&gt;transfer_notification&lt;/code&gt; can then reach the owner of that receiving jetton wallet.&lt;/p&gt;

&lt;p&gt;At this point, check the &lt;strong&gt;jetton amount&lt;/strong&gt;, not only the TON attached to the internal message.&lt;/p&gt;

&lt;p&gt;A common decoding mistake is to see a small TON value traveling with the message and assume it represents the size of the trade. For jetton swaps, the trade amount is encoded in the jetton operation. Attached TON is also used to fund execution and message forwarding.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The STON.fi Router recognizes the swap request
&lt;/h3&gt;

&lt;p&gt;The Router is where the generic jetton transfer becomes a DEX operation.&lt;/p&gt;

&lt;p&gt;STON.fi's Router documentation describes handling &lt;code&gt;transfer_notification&lt;/code&gt; messages and forwarding swap requests to the appropriate Pool. STON.fi's v2 swap documentation also defines the swap payload that accompanies the token transfer.&lt;/p&gt;

&lt;p&gt;This part of the trace is especially useful for debugging.&lt;/p&gt;

&lt;p&gt;You want to establish that:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;the correct input token arrived&lt;/li&gt;
&lt;li&gt;the expected amount was recognized&lt;/li&gt;
&lt;li&gt;the payload requested a swap&lt;/li&gt;
&lt;li&gt;the request was routed to the intended pool&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If the trace never reaches the expected Pool, the failure happened before actual AMM execution.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. The Pool executes the exchange
&lt;/h3&gt;

&lt;p&gt;The Pool is the point where the input becomes an output amount according to the pool's state and swap rules.&lt;/p&gt;

&lt;p&gt;STON.fi's v2 Pool specification includes swap-related parameters such as the minimum output and receiver information. After successful execution, the Pool can send the swap result toward the Router for settlement through the documented payout flow.&lt;/p&gt;

&lt;p&gt;When examining the Pool transaction, check more than whether an explorer colors it green.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;successful compute and action phases&lt;/li&gt;
&lt;li&gt;no relevant bounce or error downstream&lt;/li&gt;
&lt;li&gt;the output amount&lt;/li&gt;
&lt;li&gt;the receiver&lt;/li&gt;
&lt;li&gt;whether the minimum output condition was satisfied&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is often the most informative transaction in the entire trace because it connects the trade request with the resulting amount.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. The Router settles the output
&lt;/h3&gt;

&lt;p&gt;After the Pool calculates the result, the output still has to reach you.&lt;/p&gt;

&lt;p&gt;STON.fi documents the &lt;code&gt;pay_to&lt;/code&gt; operation on the Router. This operation initiates the required jetton transfer from the Router side during swap settlement.&lt;/p&gt;

&lt;p&gt;You can now follow Token B in the opposite direction from the input:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pool result -&amp;gt; Router settlement -&amp;gt; output jetton transfer -&amp;gt; your Token B jetton wallet&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you lose the trail in a large trace, search for the expected output jetton and receiver address.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Your destination jetton wallet receives Token B
&lt;/h3&gt;

&lt;p&gt;The strongest practical confirmation is the final asset movement.&lt;/p&gt;

&lt;p&gt;Find the transaction that credits the Token B jetton wallet owned by your receiving address. Confirm the token identity and amount rather than relying only on a high-level "swap successful" label.&lt;/p&gt;

&lt;p&gt;The trace may continue with excess TON refunds or other bookkeeping messages after the economic result of the swap is already clear. The jetton standard defines an &lt;code&gt;excesses&lt;/code&gt; message specifically for returning remaining TON associated with an operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do you prove the swap actually succeeded?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr42ihlngzba2vau71q4y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr42ihlngzba2vau71q4y.png" alt="How do you prove the swap actually succeeded on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A green first transaction is not enough.&lt;/p&gt;

&lt;p&gt;TON's asynchronous model allows one contract to process its message successfully while a later part of the trace encounters a different outcome. A swap should therefore be verified end to end.&lt;/p&gt;

&lt;p&gt;A strong verification uses several signals together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The input moved:&lt;/strong&gt; the correct quantity of the offer jetton left your jetton wallet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Router received the intended operation:&lt;/strong&gt; the relevant notification and STON.fi payload are visible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Pool processed the swap:&lt;/strong&gt; the pool-side transaction completed as expected.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No later failure invalidated the intended path:&lt;/strong&gt; inspect bounced or failed messages when present.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The output moved:&lt;/strong&gt; the correct ask jetton was transferred toward your receiver.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The destination balance changed:&lt;/strong&gt; your output jetton wallet received the resulting tokens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;STON.fi's API provides another convenient layer. Its swap status and transaction action endpoints can help summarize what the protocol recognized, while the raw trace remains the source for inspecting individual TON transactions and messages.&lt;/p&gt;

&lt;p&gt;This combination is much more reliable than reading only the first or last line shown by a wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Do not confuse attached TON with swap value or total fees
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn4rekzroxi51x704f019.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fn4rekzroxi51x704f019.png" alt="Do not confuse attached TON with swap value" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TON messages frequently carry TON because downstream contracts need funds to execute and send further messages.&lt;/p&gt;

&lt;p&gt;That TON can move through several contracts during one trace. Some may pay transaction and forwarding fees, and unused amounts may later return as excesses.&lt;/p&gt;

&lt;p&gt;TON's documentation describes this carry-value pattern: incoming value becomes part of the receiving contract balance, and contracts use message modes and reserve logic to fund subsequent execution.&lt;/p&gt;

&lt;p&gt;So when you see several internal transfers such as &lt;code&gt;0.05 TON&lt;/code&gt;, &lt;code&gt;0.03 TON&lt;/code&gt;, or smaller amounts, do not simply add them together and call the result the swap fee.&lt;/p&gt;

&lt;p&gt;Instead, separate three things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The asset being traded&lt;/strong&gt;, such as a jetton amount.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TON attached for execution&lt;/strong&gt;, which can continue through the trace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Actual blockchain fees&lt;/strong&gt;, recorded for the individual transactions.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;TON transactions expose their own fee information, and a multi-contract trace contains multiple transactions.&lt;/p&gt;

&lt;p&gt;For a technical investigation, inspect the fee fields rather than estimating cost from visible message values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the STON.fi action tree and raw trace together
&lt;/h2&gt;

&lt;p&gt;There are two useful ways to decode the same swap.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;raw TON view&lt;/strong&gt; answers questions such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which account processed this message?&lt;/li&gt;
&lt;li&gt;What was the incoming body?&lt;/li&gt;
&lt;li&gt;Which messages did it create?&lt;/li&gt;
&lt;li&gt;What were the exit results?&lt;/li&gt;
&lt;li&gt;How much TON was attached?&lt;/li&gt;
&lt;li&gt;Which token wallet received the output?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;STON.fi protocol view&lt;/strong&gt; answers the higher-level question: what STON.fi actions were triggered by the originating transaction?&lt;/p&gt;

&lt;p&gt;STON.fi's REST API includes &lt;code&gt;POST /v1/transaction/action_tree&lt;/code&gt;, which returns a flattened list of STON.fi actions and their statuses triggered by an originating transaction. The API reference also documents transaction resolution and swap-status functionality.&lt;/p&gt;

&lt;p&gt;For most investigations, use both.&lt;/p&gt;

&lt;p&gt;Start with the action tree to understand the likely story. Then use the blockchain trace to prove each important part of that story.&lt;/p&gt;

&lt;p&gt;That approach is faster than manually decoding every cell from the beginning, but it does not make you dependent on an indexer's interpretation.&lt;/p&gt;

&lt;h2&gt;
  
  
  A compact STON.fi swap decoding checklist
&lt;/h2&gt;

&lt;p&gt;When inspecting an unfamiliar swap, work through these checks in order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Find the complete trace&lt;/strong&gt;, not just your wallet transaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Identify the token wallets&lt;/strong&gt;, Router, Pool, and final receiver.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow the offer asset&lt;/strong&gt;, from your balance toward STON.fi.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspect the swap payload and Pool transaction&lt;/strong&gt;, including output conditions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Follow the ask asset&lt;/strong&gt;, from settlement to your receiving jetton wallet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Review failures, bounces, excesses, and fees&lt;/strong&gt; only after the main asset path is clear.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the trace is complicated, ignore unrelated branches initially. The central question is always the same: &lt;strong&gt;where did the input asset go, what contract converted it, and where did the output asset arrive?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once those three points are established, op codes, query IDs, fees, and excess messages become supporting evidence rather than noise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does a STON.fi swap have one transaction hash?
&lt;/h3&gt;

&lt;p&gt;Not necessarily in the sense Ethereum users usually expect. A TON transaction describes a state change on one account after processing a message. A STON.fi swap can involve several such transactions connected through internal messages. The useful object to inspect is therefore the full trace that begins with the wallet operation and continues through the contracts involved in the swap.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does my STON.fi swap contain so many transactions?
&lt;/h3&gt;

&lt;p&gt;Because TON smart contracts communicate asynchronously. Your wallet, jetton wallets, Router, Pool, and destination token wallet can each process separate messages and therefore generate separate transactions. Additional transactions may appear for wallet deployment, refunds, excess TON, or other execution details. A long trace does not by itself indicate that anything went wrong.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I identify a STON.fi swap from its op code?
&lt;/h3&gt;

&lt;p&gt;An op code is strong evidence, but it should not be your only check. STON.fi documents protocol-specific swap operation identifiers, while TON's jetton standard defines codes for transfers and notifications. Confirm the op code together with the contract address, message direction, token identities, amounts, and surrounding trace.&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I know whether the swap really delivered my tokens?
&lt;/h3&gt;

&lt;p&gt;Follow the output asset until the receiving jetton wallet is credited. Also confirm that the Pool and settlement transactions completed without a downstream failure that prevented the expected payout. A successful initiating wallet transaction alone is weaker evidence than seeing the actual output token movement in the trace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is the TON amount in an internal message different from my swap amount?
&lt;/h3&gt;

&lt;p&gt;For jetton swaps, the amount being traded is encoded as a jetton amount. TON attached to messages is also used to pay for contract execution and forwarding through the trace. Some unused TON can later be returned. Treat attached TON, jetton quantities, and blockchain fees as separate values when decoding the operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a TON-to-jetton swap have exactly the same trace?
&lt;/h3&gt;

&lt;p&gt;No. Native TON requires a different token path from an ordinary jetton-to-jetton exchange, so the exact contracts and messages can differ. STON.fi provides dedicated TON-to-jetton and jetton-to-TON swap methods in its DEX tooling. The same decoding principle still works: identify the input path, find the Pool execution, then follow the output to its final owner.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the fastest way to decode a STON.fi swap transaction?
&lt;/h3&gt;

&lt;p&gt;Start with the full TON trace, identify the offer and ask token flows, and compare what you see with STON.fi's transaction action tree. Use friendly explorer labels to navigate quickly, but verify important conclusions from contract addresses, message bodies, op codes, amounts, and the final token transfer. That gives you both a readable summary and low-level confirmation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;STON.fi DEX v2 Swap Examples - official message-flow examples for swaps and multi-step execution&lt;/li&gt;
&lt;li&gt;STON.fi DEX v2 Op Codes - official reference for STON.fi smart contract operation identifiers&lt;/li&gt;
&lt;li&gt;STON.fi Router v2 - official documentation for Router message handling and settlement operations&lt;/li&gt;
&lt;li&gt;STON.fi Pool v2 - official documentation for Pool state and swap-related operations&lt;/li&gt;
&lt;li&gt;STON.fi API Reference - transaction resolution, swap status, and transaction action tree endpoints&lt;/li&gt;
&lt;li&gt;TON Messages and Transactions Overview - explains how messages, account transactions, fees, and traces relate&lt;/li&gt;
&lt;li&gt;TON Traces - official explanation of causal message traces and their representation in explorers&lt;/li&gt;
&lt;li&gt;TON Jetton Standard - overview of jetton masters and per-owner jetton wallet contracts&lt;/li&gt;
&lt;li&gt;TON Connect Send Transaction - official documentation for wallet transaction requests from dApps&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Send a STON.fi Swap Transaction from a TON Wallet</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Wed, 12 Aug 2026 16:42:49 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-send-a-stonfi-swap-transaction-from-a-ton-wallet-c63</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-send-a-stonfi-swap-transaction-from-a-ton-wallet-c63</guid>
      <description>&lt;p&gt;&lt;em&gt;Build the swap with STON.fi, hand the transaction to TON Connect, and let the connected wallet sign and broadcast it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A STON.fi swap is not sent by giving your dApp access to a user's private key. Your application prepares the contract message required for the swap, converts it into a TON Connect transaction request, and asks the connected TON wallet to approve it. The wallet remains responsible for signing and broadcasting the transaction.&lt;/p&gt;

&lt;p&gt;For a modern STON.fi integration, the recommended mainnet pattern is to simulate the swap first, use the router metadata returned by STON.fi, build the corresponding transaction parameters with &lt;code&gt;@ston-fi/sdk&lt;/code&gt;, and pass those parameters to &lt;code&gt;sendTransaction()&lt;/code&gt; from TON Connect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr2n1fz5j06n4iurpueof.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr2n1fz5j06n4iurpueof.png" alt="STON.fi swap flow from TON wallet" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The full path looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect the TON wallet.&lt;/li&gt;
&lt;li&gt;Simulate the swap.&lt;/li&gt;
&lt;li&gt;Use the simulation's router information.&lt;/li&gt;
&lt;li&gt;Ask the STON.fi SDK to build the contract message.&lt;/li&gt;
&lt;li&gt;Convert that message into TON Connect format.&lt;/li&gt;
&lt;li&gt;Ask the wallet to sign and broadcast it.&lt;/li&gt;
&lt;li&gt;Verify the resulting transaction on-chain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The separation between steps 4 and 5 is particularly useful. STON.fi knows how the swap contract should be called. TON Connect knows how to request authorization from the user's wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are you actually sending?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fliznori16ygqm3wuv7bf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fliznori16ygqm3wuv7bf.png" alt="What are actually sending on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you call one of the STON.fi SDK transaction-building methods, the SDK produces transaction parameters describing an internal message. The common result contains three important fields:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Address&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Cell&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;to&lt;/code&gt; is the destination contract address. &lt;code&gt;value&lt;/code&gt; is the amount of TON that must accompany the message. &lt;code&gt;body&lt;/code&gt; is the serialized contract payload describing the operation that STON.fi should execute.&lt;/p&gt;

&lt;p&gt;Your dApp does not sign this message.&lt;/p&gt;

&lt;p&gt;Instead, it transforms those parameters into something TON Connect can send to the wallet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
  &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction is worth remembering:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STON.fi SDK builds the swap message. TON Connect requests the wallet signature. The wallet broadcasts the transaction.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TON itself is message-driven. Smart contracts receive messages, process their payloads, and may generate transactions that change contract state. The payload created by the STON.fi SDK is therefore not arbitrary metadata. It is the instruction that the relevant contract will interpret when the message arrives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up TON Connect first
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnbn9juab3onh340ohxbm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnbn9juab3onh340ohxbm.png" alt="Set up TON Connect" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a React dApp, TON documentation recommends &lt;code&gt;@tonconnect/ui-react&lt;/code&gt;. The package provides &lt;code&gt;TonConnectUIProvider&lt;/code&gt;, &lt;code&gt;TonConnectButton&lt;/code&gt;, &lt;code&gt;useTonConnectUI&lt;/code&gt;, and wallet-state hooks that you can use without handling private keys yourself.&lt;/p&gt;

&lt;p&gt;Install the packages needed for the basic STON.fi flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @ston-fi/sdk @ston-fi/api @tonconnect/ui-react @ton/ton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You also need a public TON Connect manifest. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://swap.example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My STON.fi Swap App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iconUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://swap.example.com/icon-180.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In production, TON requires the manifest to be publicly reachable, and current documentation says it should be served through HTTPS. The wallet uses this metadata to identify the dApp during connection.&lt;/p&gt;

&lt;p&gt;Wrap your React app with the provider:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectUIProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;
      &lt;span class="na"&gt;manifestUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://swap.example.com/tonconnect-manifest.json"&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then expose the wallet connection button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside your swap component you can read the connected address and access the transaction API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;userAddress&lt;/code&gt; is empty, there is no connected account available to sign the swap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulate before building the transaction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsygev5z99t9pjgnr6p1k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsygev5z99t9pjgnr6p1k.png" alt="Why simulate the swap first on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For STON.fi v2 mainnet swaps, hardcoding a router is not the preferred production pattern. STON.fi documentation recommends obtaining routing information from the API and using the router returned by the simulation. This lets the integration follow the router selected for the actual swap instead of assuming one specific contract configuration.&lt;/p&gt;

&lt;p&gt;A simplified simulation looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simulateSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;slippageTolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The amount supplied as &lt;code&gt;offerUnits&lt;/code&gt; must already be expressed in the asset's smallest units. Do not assume that every TON ecosystem asset uses the same number of decimals. The STON.fi quickstart explicitly uses asset metadata when converting user-facing amounts into blockchain units.&lt;/p&gt;

&lt;p&gt;A simulation is useful for more than displaying an estimated output. It gives the transaction-building stage values such as the offer amount, minimum acceptable output, token addresses, and router information associated with that swap.&lt;/p&gt;

&lt;p&gt;That creates an important safety boundary in your UI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;changing the input asset should invalidate the old simulation&lt;/li&gt;
&lt;li&gt;changing the output asset should invalidate it&lt;/li&gt;
&lt;li&gt;changing the amount should invalidate it&lt;/li&gt;
&lt;li&gt;changing the slippage setting should trigger a new simulation&lt;/li&gt;
&lt;li&gt;the transaction should be built from the current simulation, not from stale UI state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You want the transaction the wallet sees to correspond to the swap the user just reviewed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the STON.fi swap message
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvt89ljqg6lmq9qf88ica.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvt89ljqg6lmq9qf88ica.png" alt="Build the STON.fi swap message" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you have a valid simulation and connected wallet, create the router from the router metadata supplied by STON.fi.&lt;/p&gt;

&lt;p&gt;A compact version of the current API-driven pattern looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://toncenter.com/api/v2/jsonRPC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routerInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dexContracts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;dexContracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dexContracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;STON.fi's current v2 documentation specifically recommends feeding the router returned by the simulation into &lt;code&gt;dexFactory()&lt;/code&gt; for mainnet-facing integrations rather than hardcoding the router contract.&lt;/p&gt;

&lt;p&gt;Next, prepare the fields shared by the swap variants:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharedTxParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;offerAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;minAskAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minAskUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact builder depends on what you are swapping.&lt;/p&gt;

&lt;h3&gt;
  
  
  TON to jetton
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapTonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sharedTxParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Jetton to TON
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToTonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sharedTxParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Jetton to jetton
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sharedTxParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important result is the same in each case: you receive the destination, attached TON value, and payload needed for the contract call. STON.fi documents separate transaction builders for TON-to-jetton, jetton-to-TON, and jetton-to-jetton swaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send the transaction through the TON wallet
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmoa5buo8ogycx8icuxdl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmoa5buo8ogycx8icuxdl.png" alt="Send the transaction through the TON wallet" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the STON.fi-specific construction work is finished.&lt;/p&gt;

&lt;p&gt;The remaining step is to hand the message to the wallet through TON Connect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;validUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is the point where the wallet UI should appear and ask the user to review and approve the transaction.&lt;/p&gt;

&lt;p&gt;There are several details here that are easy to overlook.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;address&lt;/code&gt;&lt;/strong&gt; comes directly from the STON.fi transaction parameters. Do not replace it with the address of the asset, pool, or some router address stored elsewhere in your UI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;amount&lt;/code&gt;&lt;/strong&gt; is the TON value attached to the contract message. Pass the SDK-generated value rather than manually reconstructing the gas requirement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;payload&lt;/code&gt;&lt;/strong&gt; is the contract body serialized as a Bag of Cells and encoded in base64 so TON Connect can include it in the outgoing message.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;validUntil&lt;/code&gt;&lt;/strong&gt; is a Unix timestamp in seconds. Current TON Connect documentation defines it in seconds and shows the pattern &lt;code&gt;Math.floor(Date.now() / 1000) + 600&lt;/code&gt;. Some older examples in the ecosystem use &lt;code&gt;Date.now()&lt;/code&gt; directly, which produces milliseconds, so this is a field worth checking carefully when adapting existing code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;network&lt;/code&gt;&lt;/strong&gt; should be set explicitly. TON Connect currently identifies TON mainnet as &lt;code&gt;-239&lt;/code&gt; and testnet as &lt;code&gt;-3&lt;/code&gt;. If the requested network conflicts with the wallet's connected network, the wallet can reject the request.&lt;/p&gt;

&lt;p&gt;STON.fi's transaction-sending guide uses the same underlying pattern: obtain &lt;code&gt;to&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, and &lt;code&gt;body&lt;/code&gt; from the SDK, then pass them to the wallet implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Put the full handler together
&lt;/h2&gt;

&lt;p&gt;Here is the essential flow in one React handler:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dexFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SwapButton&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSwap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connect a wallet first&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Simulate the swap first&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://toncenter.com/api/v2/jsonRPC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routerInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dexContracts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;dexContracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dexContracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sharedTxParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;offerAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;minAskAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minAskUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;swapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapTonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sharedTxParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;swapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToTonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sharedTxParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;swapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;sharedTxParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;simulationResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;validUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="nx"&gt;swapParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;
              &lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
              &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Wallet response:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSwap&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Swap
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code intentionally keeps quote generation separate from transaction sending. In a real application, you should also disable the button while a request is in progress, handle rejected wallet requests separately from network failures, refresh stale simulations, and display useful status feedback.&lt;/p&gt;

&lt;p&gt;TON Connect documents &lt;code&gt;USER_REJECTS_ERROR&lt;/code&gt; separately from malformed requests and unsupported methods, so a user pressing "Cancel" should not be presented as a protocol failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens after the wallet approves?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi4m763t9n7j1nefcc99n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fi4m763t9n7j1nefcc99n.png" alt="What happens after the wallet approves" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sendTransaction()&lt;/code&gt; asks the connected wallet to sign and broadcast the outgoing message. Current TON Connect documentation says the response can contain the base64 BoC of the broadcast external message, which can then be used as part of an on-chain lookup or tracking flow.&lt;/p&gt;

&lt;p&gt;A resolved wallet promise should therefore not be treated as "the swap is definitely complete."&lt;/p&gt;

&lt;p&gt;There are several different states your interface may need to distinguish:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the wallet request was opened&lt;/li&gt;
&lt;li&gt;the user approved the request&lt;/li&gt;
&lt;li&gt;the wallet broadcast the external message&lt;/li&gt;
&lt;li&gt;the relevant contract received and processed the internal message&lt;/li&gt;
&lt;li&gt;the swap completed successfully on-chain&lt;/li&gt;
&lt;li&gt;the resulting token balances became visible in your application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;TON transactions are produced as contracts process messages, so wallet authorization and smart contract execution are related but not identical events.&lt;/p&gt;

&lt;p&gt;For a production interface, update the UI only when you have enough evidence for the state you are displaying. "Transaction submitted" is more accurate immediately after wallet submission than "Swap completed."&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes when sending STON.fi swaps
&lt;/h2&gt;

&lt;p&gt;Most integration failures around this final step come from a small number of mismatches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Building from stale simulation data.&lt;/strong&gt; If the amount or asset changes after simulation, create a new simulation before building the transaction.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardcoding a production router.&lt;/strong&gt; Current STON.fi v2 guidance favors the router metadata returned by its mainnet API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recreating the payload manually.&lt;/strong&gt; Let the STON.fi SDK produce the contract body unless you have a specific low-level reason to construct the message yourself.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using the wrong time unit for &lt;code&gt;validUntil&lt;/code&gt;.&lt;/strong&gt; TON Connect currently expects Unix seconds, not JavaScript milliseconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assuming wallet approval equals swap completion.&lt;/strong&gt; Submission still has to result in successful on-chain contract execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating cancellation as an execution error.&lt;/strong&gt; A user can simply reject the wallet prompt, and TON Connect exposes a specific rejection error for that case.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing copied mainnet addresses or amounts blindly.&lt;/strong&gt; TON's current documentation explicitly warns that mainnet transfers are irreversible and recommends replacing sample values and testing appropriately before using real funds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical takeaway:&lt;/strong&gt; keep the integration boundary simple. Use the STON.fi API to simulate the current swap, let &lt;code&gt;dexFactory()&lt;/code&gt; and the relevant router helper produce the exact transaction parameters, then pass those parameters almost unchanged into TON Connect. Your dApp should coordinate the process, not sign on behalf of the user and not guess the contract payload.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does my dApp need the user's TON wallet seed phrase to send a STON.fi swap?
&lt;/h3&gt;

&lt;p&gt;No. A normal client-side TON Connect integration should not obtain the user's seed phrase or private key. Your application constructs the requested transaction, while the connected wallet handles approval, signing, and broadcasting. This separation is one of the main reasons to integrate through TON Connect rather than importing wallet credentials into the application.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does the STON.fi SDK actually provide to TON Connect?
&lt;/h3&gt;

&lt;p&gt;The SDK provides the information required for the contract message, including its destination, attached TON value, and payload cell. Your application serializes the payload to a base64 BoC and places these values inside the &lt;code&gt;messages&lt;/code&gt; array passed to &lt;code&gt;sendTransaction()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why should I simulate the swap before sending it?
&lt;/h3&gt;

&lt;p&gt;Simulation gives you the swap-specific values needed to review and build the transaction, including the minimum output and router information used by the current API-driven v2 workflow. It also gives your interface a natural point to show the expected result before asking the wallet for authorization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should &lt;code&gt;validUntil&lt;/code&gt; use milliseconds or seconds?
&lt;/h3&gt;

&lt;p&gt;Use Unix seconds. Current TON Connect documentation defines &lt;code&gt;validUntil&lt;/code&gt; as Unix seconds and demonstrates it with &lt;code&gt;Math.floor(Date.now() / 1000) + ...&lt;/code&gt;. This is important because JavaScript's &lt;code&gt;Date.now()&lt;/code&gt; alone returns milliseconds.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does &lt;code&gt;network: "-239"&lt;/code&gt; mean?
&lt;/h3&gt;

&lt;p&gt;It identifies TON mainnet in the current TON Connect transaction request format. Testnet is identified as &lt;code&gt;-3&lt;/code&gt;. Setting the network explicitly lets the wallet reject a transaction request if the connected account is on an incompatible network.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can the same wallet flow handle TON-to-jetton and jetton-to-jetton swaps?
&lt;/h3&gt;

&lt;p&gt;Yes, but the STON.fi SDK method used to construct the transaction differs by swap type. The final TON Connect step still follows the same basic model: take the resulting destination, attached value, and payload, then request wallet approval through &lt;code&gt;sendTransaction()&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a successful &lt;code&gt;sendTransaction()&lt;/code&gt; response prove that the STON.fi swap finished?
&lt;/h3&gt;

&lt;p&gt;Not by itself. It proves that the wallet-side transaction request reached the submission stage represented by TON Connect's response. Contract processing happens on-chain afterward, so a production dApp should track or verify the resulting operation before presenting the swap as completed.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should I verify immediately before sending a STON.fi swap from a TON wallet?
&lt;/h3&gt;

&lt;p&gt;Verify that the wallet is still connected, the simulation still matches the selected assets and amount, the minimum output reflects the intended slippage setting, the router comes from the current simulation, and the transaction parameters were generated by the matching STON.fi SDK helper. Only then transform those parameters into the TON Connect request shown to the wallet for approval.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;STON.fi Swap Guide (React) - Official end-to-end React example covering wallet connection, swap simulation, router selection, transaction construction, and TonConnect execution&lt;/li&gt;
&lt;li&gt;STON.fi Swap v2 documentation - Official v2 swap documentation describing the API-driven mainnet workflow and dynamic router construction&lt;/li&gt;
&lt;li&gt;STON.fi Transaction Sending - Official explanation of the &lt;code&gt;to&lt;/code&gt;, &lt;code&gt;value&lt;/code&gt;, and &lt;code&gt;body&lt;/code&gt; transaction parameters returned by SDK transaction builders&lt;/li&gt;
&lt;li&gt;STON.fi Via TonConnect - Official STON.fi example for converting SDK transaction parameters into a TonConnect transaction request&lt;/li&gt;
&lt;li&gt;TON Connect Get Started - Official TON documentation for manifests, React integration, wallet connection, providers, and the TON Connect SDK choices&lt;/li&gt;
&lt;li&gt;TON Connect Send a Transaction - Official current specification for &lt;code&gt;sendTransaction&lt;/code&gt;, &lt;code&gt;validUntil&lt;/code&gt;, network identifiers, raw messages, responses, and wallet errors&lt;/li&gt;
&lt;li&gt;TON Messages and Transactions Overview - Official TON explanation of how messages are processed and how contract state changes become transactions&lt;/li&gt;
&lt;li&gt;STON.fi API Client Source - Official STON.fi API implementation showing the API client and router-related methods used by developer integrations&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Connect TON Connect to a STON.fi dApp</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Thu, 06 Aug 2026 06:34:41 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-connect-ton-connect-to-a-stonfi-dapp-5glh</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-connect-ton-connect-to-a-stonfi-dapp-5glh</guid>
      <description>&lt;p&gt;&lt;em&gt;A practical React integration that connects a TON wallet, reads the wallet state, builds a STON.fi swap, and hands the transaction back to the wallet for approval.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Connecting TON Connect to a STON.fi dApp means giving your application a standard way to discover the user's TON wallet, read the connected address, and request transaction signatures without ever handling the user's private keys.&lt;/p&gt;

&lt;p&gt;For a STON.fi swap interface, the flow is straightforward: TON Connect manages the wallet session, the STON.fi API simulates the swap, the STON.fi SDK builds the contract message, and TON Connect asks the wallet to sign and broadcast it. The dApp coordinates these pieces, but the wallet remains the signing authority throughout the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  What TON Connect actually does in a STON.fi dApp
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fokoc202amuuz6vohroq1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fokoc202amuuz6vohroq1.png" alt="How integration works on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It helps to separate wallet connectivity from DEX logic.&lt;/p&gt;

&lt;p&gt;STON.fi does not need your application to obtain a seed phrase or private key. Instead, TON Connect creates a communication layer between the dApp and a compatible wallet. After the person chooses a wallet and approves the connection, your frontend receives account information that can be used when preparing STON.fi transactions.&lt;/p&gt;

&lt;p&gt;A typical integration has four responsibilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;TON Connect&lt;/strong&gt; manages connection, reconnection, wallet selection, and transaction requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;STON.fi API&lt;/strong&gt; supplies current asset and swap simulation information.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;STON.fi SDK&lt;/strong&gt; converts swap parameters into contract transaction data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The wallet&lt;/strong&gt; reviews, signs, and broadcasts the transaction.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The official STON.fi React quickstart uses exactly this division of responsibilities, combining &lt;code&gt;@tonconnect/ui-react&lt;/code&gt;, &lt;code&gt;@ston-fi/api&lt;/code&gt;, and &lt;code&gt;@ston-fi/sdk&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The wallet connection therefore does not perform a swap by itself. It gives your STON.fi integration the address and signing channel needed to perform one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up the React dependencies
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3a9pezvu15h1liz656g5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3a9pezvu15h1liz656g5.png" alt="Set up the React dependencies on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a React dApp, install the TON Connect React package together with the STON.fi SDK and API client.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @tonconnect/ui-react @ston-fi/sdk @ston-fi/api
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the rest of your application, you may also use TON libraries for blockchain utilities and amount conversion.&lt;/p&gt;

&lt;p&gt;The important architectural point is to keep the responsibilities separate. Avoid implementing wallet-specific connection code for Tonkeeper, MyTonWallet, or other individual wallets when TON Connect already provides a common interface.&lt;/p&gt;

&lt;p&gt;The official TON documentation describes &lt;code&gt;@tonconnect/ui-react&lt;/code&gt; as the React binding around TON Connect UI. It provides the application provider, the standard wallet button, and hooks for accessing the connection and wallet state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the TON Connect manifest first
&lt;/h2&gt;

&lt;p&gt;Every TON Connect dApp needs a manifest that tells wallets which application is requesting the connection.&lt;/p&gt;

&lt;p&gt;Create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public/tonconnect-manifest.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A minimal version looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-dapp.example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My STON.fi dApp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iconUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-dapp.example/icon-180.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also provide privacy policy and terms URLs when appropriate.&lt;/p&gt;

&lt;p&gt;The manifest is not just decoration. Wallets fetch it to identify your application before presenting the connection request. The URL and icon should therefore point to real public resources when you deploy the dApp.&lt;/p&gt;

&lt;p&gt;Before debugging your React code, open the manifest URL directly in a browser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-dapp.example/tonconnect-manifest.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If it cannot be fetched there, a wallet may not be able to fetch it either.&lt;/p&gt;

&lt;p&gt;A useful deployment checklist is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Serve the manifest over HTTPS in production.&lt;/li&gt;
&lt;li&gt;Use your real dApp domain.&lt;/li&gt;
&lt;li&gt;Make the icon publicly accessible.&lt;/li&gt;
&lt;li&gt;Keep the application name recognizable.&lt;/li&gt;
&lt;li&gt;Do not copy another project's manifest unchanged.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For local development, STON.fi's React guide demonstrates serving the manifest from the application's public directory and pointing the provider at the current origin.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add TON Connect to the React component tree
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8jnwnmbd8497ghln240i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8jnwnmbd8497ghln240i.png" alt="Add TON connect to React on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The next step is to wrap the application in &lt;code&gt;TonConnectUIProvider&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For a Vite-based React project, your entry file can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectUIProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;
      &lt;span class="na"&gt;manifestUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tonconnect-manifest.json`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything that calls TON Connect React hooks must be rendered beneath this provider.&lt;/p&gt;

&lt;p&gt;You can then add the standard connection button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Header&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clicking it opens the TON Connect wallet picker. After a successful connection, the same component reflects the connected state automatically.&lt;/p&gt;

&lt;p&gt;You can build your own button and call &lt;code&gt;openModal()&lt;/code&gt; if your design requires a custom interface, but starting with &lt;code&gt;TonConnectButton&lt;/code&gt; removes unnecessary connection logic while you build the rest of the STON.fi integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the connected wallet correctly
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkv3tdevot35yf7uzbnhw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkv3tdevot35yf7uzbnhw.png" alt="Read the wallet state on STON.fi correctly" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A STON.fi swap needs the connected wallet address because that address becomes part of the transaction parameters.&lt;/p&gt;

&lt;p&gt;TON Connect exposes it through hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useIsConnectionRestored&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonWallet&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WalletStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;restored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useIsConnectionRestored&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonWallet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;restored&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Restoring wallet connection...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Connect a wallet to continue.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Connected: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useIsConnectionRestored()&lt;/code&gt; deserves special attention. TON Connect attempts to restore an existing session when the application loads. Until that process finishes, a missing wallet does not necessarily mean that the person is disconnected. Redirecting or disabling your interface too early can create a visible connection flicker or incorrect state. TON's documentation specifically recommends waiting for restoration before making that decision.&lt;/p&gt;

&lt;p&gt;For your swap interface, that gives you a simple state model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connection state is still being restored.&lt;/li&gt;
&lt;li&gt;No wallet is connected.&lt;/li&gt;
&lt;li&gt;A wallet is connected and the swap interface can use its address.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do not confuse wallet connection with authentication. If your backend needs cryptographic proof that a person controls an address, TON Connect also supports &lt;code&gt;ton_proof&lt;/code&gt;. A plain connected address is useful for transaction construction, but it should not automatically become a trusted login credential for a sensitive backend session.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect the wallet state to a STON.fi swap
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmp5ii7rowimvikf62p3s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fmp5ii7rowimvikf62p3s.png" alt="Build and send a swap on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now the two systems meet.&lt;/p&gt;

&lt;p&gt;For production STON.fi swaps, the current v2 documentation recommends an API-driven approach rather than hardcoding a router address. Your dApp first simulates the swap, receives router metadata, creates the matching SDK contracts, and then builds the transaction parameters.&lt;/p&gt;

&lt;p&gt;Conceptually, the flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Connected wallet
      |
      v
STON.fi swap simulation
      |
      v
Router metadata
      |
      v
STON.fi SDK builds transaction
      |
      v
TON Connect sendTransaction()
      |
      v
Wallet approval
      |
      v
TON blockchain
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is a focused example for a TON-to-jetton swap:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useTonConnectUI&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toUnits&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://toncenter.com/api/v2/jsonRPC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SwapButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;swap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connect a wallet first&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simulateSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;jetton-master-address&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;toUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;slippageTolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routerInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dexContracts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;dexContracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dexContracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapTonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;offerAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;minAskAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minAskUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;queryId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;validUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;swap&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Swap with STON.fi
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact token addresses and input amounts should come from your interface rather than hardcoded production values.&lt;/p&gt;

&lt;p&gt;The current STON.fi v2 guidance is especially important here: the REST API returns router information with the simulation result, and &lt;code&gt;dexFactory()&lt;/code&gt; lets the SDK construct contracts appropriate for that router. This avoids making your integration depend on one manually selected production router.&lt;/p&gt;

&lt;h2&gt;
  
  
  What happens when &lt;code&gt;sendTransaction()&lt;/code&gt; runs?
&lt;/h2&gt;

&lt;p&gt;The STON.fi SDK does not need to sign anything.&lt;/p&gt;

&lt;p&gt;Its job is to produce parameters such as the destination address, attached TON value, and serialized payload. Your code converts those values into a TON Connect transaction request.&lt;/p&gt;

&lt;p&gt;TON Connect then presents that request to the wallet.&lt;/p&gt;

&lt;p&gt;For raw transaction messages, the important fields are:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;address&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Contract or wallet receiving the message&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;amount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TON value attached in the smallest unit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;payload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Base64 encoded contract message body&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validUntil&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unix timestamp after which the request is invalid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;network&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;TON network expected by the dApp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;According to the current TON Connect transaction specification, &lt;code&gt;validUntil&lt;/code&gt; uses Unix seconds. For mainnet, the network identifier is &lt;code&gt;-239&lt;/code&gt;; testnet uses &lt;code&gt;-3&lt;/code&gt;. TON also recommends specifying the network explicitly so a request is rejected if the connected wallet is on a different network.&lt;/p&gt;

&lt;p&gt;When the wallet approves the request, it signs and broadcasts the transaction. Your frontend never receives the private key.&lt;/p&gt;

&lt;p&gt;That boundary is one of the most important design principles in the integration:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;STON.fi prepares the DEX action. TON Connect transports the signing request. The wallet authorizes it.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoid the integration mistakes that cause most problems
&lt;/h2&gt;

&lt;p&gt;The basic connection takes only a small amount of code. Most problems appear around state management, transaction construction, or assumptions about the network.&lt;/p&gt;

&lt;p&gt;Before shipping, check these areas.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not hardcode production routing when the STON.fi API can provide it.&lt;/strong&gt; Current STON.fi v2 documentation recommends simulating first and using the router object returned by the API with &lt;code&gt;dexFactory()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not treat a stale simulation as a guaranteed execution price.&lt;/strong&gt; Pool conditions can change between simulation and wallet confirmation. Use the minimum output calculated for the swap and refresh quotes when appropriate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not mix milliseconds and Unix seconds in &lt;code&gt;validUntil&lt;/code&gt;.&lt;/strong&gt; The current TON Connect request format expects seconds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not enable the swap while the wallet state is unresolved.&lt;/strong&gt; Wait for connection restoration and require an address before generating transaction parameters.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not manually ask for a seed phrase.&lt;/strong&gt; A normal TON Connect integration has no reason to request one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not assume &lt;code&gt;sendTransaction()&lt;/code&gt; means the complete swap succeeded.&lt;/strong&gt; It means the wallet accepted the request and broadcast the signed message. Your interface should separately track the resulting on-chain execution if it needs a final success state.&lt;/p&gt;

&lt;p&gt;There is another TON-specific detail worth remembering. Smart contract interactions can involve multiple messages, and execution across recipient contracts is not automatically equivalent to one atomic operation. STON.fi documentation also describes refund behavior for swaps when execution conditions are not satisfied.&lt;/p&gt;

&lt;p&gt;For a production interface, show transaction states such as submitted, processing, completed, and failed instead of changing the button directly from "Swap" to "Success" as soon as the wallet returns.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical STON.fi integration checklist
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6pmtb8d55k70d15ddjkl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6pmtb8d55k70d15ddjkl.png" alt="STON.fi integration checklist" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At this point, you can test the entire connection as one continuous workflow.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load the dApp and wait for TON Connect session restoration.&lt;/li&gt;
&lt;li&gt;Connect a compatible TON wallet.&lt;/li&gt;
&lt;li&gt;Confirm that your application receives the correct address.&lt;/li&gt;
&lt;li&gt;Select a source asset, destination asset, and amount.&lt;/li&gt;
&lt;li&gt;Request a fresh STON.fi swap simulation.&lt;/li&gt;
&lt;li&gt;Review the expected output and minimum output in your interface.&lt;/li&gt;
&lt;li&gt;Build the matching transaction through the STON.fi SDK.&lt;/li&gt;
&lt;li&gt;Pass the resulting message to &lt;code&gt;tonConnectUI.sendTransaction()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Review the transaction inside the wallet before signing.&lt;/li&gt;
&lt;li&gt;Track the resulting blockchain operation rather than relying only on the frontend request state.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;STON.fi's official developer documentation recommends using its SDK together with TON Connect for production application interaction instead of manually constructing low-level contract BOCs unless you have a specialized reason to do so.&lt;/p&gt;

&lt;p&gt;The practical takeaway is simple: keep wallet connection, quote generation, transaction construction, and transaction signing as separate layers. Once those boundaries are clear, TON Connect becomes a small but critical bridge between your STON.fi frontend and the wallet that actually authorizes the swap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does STON.fi require TON Connect?
&lt;/h3&gt;

&lt;p&gt;A frontend can interact with TON contracts through other technical signing setups, but TON Connect is the standard wallet connection approach for user-facing TON dApps. STON.fi's own React swap quickstart integrates &lt;code&gt;@tonconnect/ui-react&lt;/code&gt; with the STON.fi API and SDK, making it the natural approach for a browser-based application where users sign transactions with their own wallets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does TON Connect give my dApp the user's private key?
&lt;/h3&gt;

&lt;p&gt;No. TON Connect creates a connection with the wallet and lets the dApp submit signing requests. The private key remains under the wallet's control. Your application receives account information and transaction responses, not the seed phrase or private signing key. A dApp asking users to enter their seed phrase is not following the normal TON Connect model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need a &lt;code&gt;tonconnect-manifest.json&lt;/code&gt; file?
&lt;/h3&gt;

&lt;p&gt;Yes. The manifest identifies your dApp to compatible wallets and includes information such as the application URL, name, and icon. Host it at a publicly accessible URL and pass that URL to &lt;code&gt;TonConnectUIProvider&lt;/code&gt;. Optional fields can also point to your terms of use and privacy policy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use &lt;code&gt;useTonAddress()&lt;/code&gt; or &lt;code&gt;useTonWallet()&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Use whichever matches the information you need. A STON.fi transaction often needs the connected address, so &lt;code&gt;useTonAddress()&lt;/code&gt; is convenient. &lt;code&gt;useTonWallet()&lt;/code&gt; gives you the broader connected wallet object. It is also useful to combine them with &lt;code&gt;useIsConnectionRestored()&lt;/code&gt; so your interface does not mistake an unfinished restoration attempt for a disconnected wallet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is connecting a wallet the same as authenticating a user?
&lt;/h3&gt;

&lt;p&gt;No. A wallet connection gives your frontend an account and a communication session. If you need secure backend authentication, TON Connect supports &lt;code&gt;ton_proof&lt;/code&gt;, where the wallet signs proof data that your server verifies. You generally do not need to introduce backend authentication merely to let a connected wallet review and sign a normal STON.fi transaction.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why should a STON.fi dApp simulate the swap before building the transaction?
&lt;/h3&gt;

&lt;p&gt;Simulation gives your application current execution information, including expected amounts, minimum output, and router metadata. Current STON.fi v2 documentation recommends an API-driven production flow in which the simulation result determines the router passed to &lt;code&gt;dexFactory()&lt;/code&gt;. That is safer for maintainability than tying the integration permanently to one hardcoded router address.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use the STON.fi REST API for testnet swaps?
&lt;/h3&gt;

&lt;p&gt;The current STON.fi v2 SDK documentation states that the REST API at &lt;code&gt;api.ston.fi&lt;/code&gt; serves mainnet data. You can test TON Connect itself and lower-level contract integrations separately, but do not assume the production API-driven STON.fi simulation flow automatically maps to testnet. Follow the specific STON.fi testnet documentation when testing contract operations there.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should I verify before letting someone sign a STON.fi swap?
&lt;/h3&gt;

&lt;p&gt;Check that the wallet is connected, the simulation is fresh, the source and destination assets are correct, the amount uses the correct token decimals, the minimum output reflects the intended slippage tolerance, and the transaction is being sent on the expected network. Then let the wallet provide the final approval step instead of attempting to sign anything inside your frontend.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TON Connect, Get started - Official introduction to manifests and TON Connect integration paths&lt;/li&gt;
&lt;li&gt;TON Connect, Connect a wallet - Official documentation for the provider, wallet button, connection restoration, wallet state, and &lt;code&gt;ton_proof&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;TON Connect, Send a transaction - Official request format for &lt;code&gt;sendTransaction()&lt;/code&gt;, including &lt;code&gt;validUntil&lt;/code&gt;, network selection, and raw messages&lt;/li&gt;
&lt;li&gt;TON Connect React API - Reference for &lt;code&gt;TonConnectUIProvider&lt;/code&gt;, &lt;code&gt;TonConnectButton&lt;/code&gt;, &lt;code&gt;useTonConnectUI&lt;/code&gt;, &lt;code&gt;useTonAddress&lt;/code&gt;, and wallet hooks&lt;/li&gt;
&lt;li&gt;STON.fi Swap Guide (React) - Official end-to-end example combining TON Connect, the STON.fi API, and the STON.fi SDK&lt;/li&gt;
&lt;li&gt;STON.fi SDK v2 Swap - Official production guidance for simulation, dynamic router selection, &lt;code&gt;dexFactory()&lt;/code&gt;, and v2 swap construction&lt;/li&gt;
&lt;li&gt;STON.fi SDK - Overview of the TypeScript and JavaScript SDK and current DEX contract integration tools&lt;/li&gt;
&lt;li&gt;STON.fi REST API Reference - Official API overview covering swap simulation, swap status, pools, assets, and related DEX data&lt;/li&gt;
&lt;li&gt;STON.fi DEX v2 Smart Contracts - Contract-level documentation and the recommendation to use the official SDK with TON Connect for production application integrations&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Build a Basic STON.fi Swap Interface</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Mon, 03 Aug 2026 09:25:49 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-build-a-basic-stonfi-swap-interface-1l2a</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-build-a-basic-stonfi-swap-interface-1l2a</guid>
      <description>&lt;p&gt;&lt;em&gt;A practical React guide to wallet connection, token selection, swap simulation, transaction building, and on-chain execution on TON.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A basic STON.fi swap interface needs to do much more than place two token selectors next to a Swap button. A useful implementation has to connect a TON wallet, load supported assets, convert human-readable amounts into blockchain units, simulate the trade, preserve the resulting slippage protection, build the correct STON.fi transaction, and finally ask the wallet to sign it.&lt;/p&gt;

&lt;p&gt;The cleanest architecture separates those responsibilities. STON.fi provides a REST API for asset data and swap simulation, its TypeScript SDK builds the contract transaction, and TON Connect handles wallet interaction. Your frontend coordinates the three without ever taking custody of the user's private keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the interface actually needs to do
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fimmvzg8qxru4k33icscr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fimmvzg8qxru4k33icscr.png" alt="What the interface actually needs to do in STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a minimal React application, think of the swap as five connected states:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Wallet state:&lt;/strong&gt; Is a TON wallet connected, and what is its address?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asset state:&lt;/strong&gt; Which token is being sold and which token is being received?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amount state:&lt;/strong&gt; How many blockchain units does the entered amount represent?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simulation state:&lt;/strong&gt; What route, minimum output, and Router should the transaction use?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transaction state:&lt;/strong&gt; Has the wallet received, rejected, or submitted the transaction?&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That division matters because a swap quote is not permanent. If the user changes the source token, destination token, or amount, the previous simulation should immediately become invalid.&lt;/p&gt;

&lt;p&gt;A minimal interface therefore needs only a few visible controls:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect Wallet&lt;/li&gt;
&lt;li&gt;From token selector&lt;/li&gt;
&lt;li&gt;To token selector&lt;/li&gt;
&lt;li&gt;Amount input&lt;/li&gt;
&lt;li&gt;Simulated output&lt;/li&gt;
&lt;li&gt;Minimum received&lt;/li&gt;
&lt;li&gt;Swap button&lt;/li&gt;
&lt;li&gt;Loading, rejection, and transaction status messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can add charts, token balances, price impact displays, routing information, or transaction history later. They are useful improvements, but they are not required to understand the core STON.fi flow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up the React project
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx11xxqpn1go0ruktyvot.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx11xxqpn1go0ruktyvot.png" alt="React project for STON.fi swap" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;STON.fi's official React quickstart uses its API client, DEX SDK, and TON Connect together. The essential dependencies are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @ston-fi/sdk @ston-fi/api @tonconnect/ui-react @ton/ton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The roles are intentionally different.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@ston-fi/api&lt;/code&gt; gives the frontend access to STON.fi data and simulation methods. &lt;code&gt;@ston-fi/sdk&lt;/code&gt; converts the selected swap into contract-ready transaction parameters. &lt;code&gt;@tonconnect/ui-react&lt;/code&gt; connects the application to the user's wallet and submits the transaction for approval.&lt;/p&gt;

&lt;p&gt;A simple component tree might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App
├── TonConnectButton
└── SwapForm
    ├── FromAssetSelect
    ├── AmountInput
    ├── ToAssetSelect
    ├── QuotePanel
    └── SwapButton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You do not need to split the first prototype into that many files. One &lt;code&gt;App.jsx&lt;/code&gt; component is perfectly reasonable while learning the flow. The important part is keeping the logical stages separate in your state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect a TON wallet first
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx6gzknydrrwmkec7gxf6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fx6gzknydrrwmkec7gxf6.png" alt="Connect a TON wallet and load assets on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TON Connect is the standard wallet connection protocol for TON applications. The dApp receives the connected account and can request signatures or transactions, but the wallet retains control of the keys.&lt;/p&gt;

&lt;p&gt;Wrap the React application with &lt;code&gt;TonConnectUIProvider&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectUIProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;
  &lt;span class="na"&gt;manifestUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tonconnect-manifest.json`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then place a connect button somewhere visible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;TonConnectButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;walletAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The manifest is not an optional branding detail. Wallets use it to identify your application. Host &lt;code&gt;tonconnect-manifest.json&lt;/code&gt; from your own domain and provide your real application name, URL, and icon.&lt;/p&gt;

&lt;p&gt;A basic file looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"My STON.fi Swap"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iconUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/icon.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, avoid copying another project's manifest or permanently pointing to a demo manifest. The wallet approval screen should identify the application the user is actually interacting with.&lt;/p&gt;

&lt;h2&gt;
  
  
  Load assets without assuming every token has nine decimals
&lt;/h2&gt;

&lt;p&gt;The next job is populating the two asset selectors.&lt;/p&gt;

&lt;p&gt;STON.fi exposes asset information through its REST API, including an asset query endpoint. The official API client wraps those calls, so you can initialize it directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then fetch assets when the application loads and keep the result in React state.&lt;/p&gt;

&lt;p&gt;One implementation detail deserves more attention than it usually gets: &lt;strong&gt;do not assume every asset uses nine decimal places.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A wallet might display &lt;code&gt;1.25 TOKEN&lt;/code&gt;, while the blockchain and STON.fi API work with integer base units. The conversion depends on that token's metadata.&lt;/p&gt;

&lt;p&gt;For example, with nine decimals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.25 TOKEN = 1,250,000,000 units
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With six decimals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1.25 TOKEN = 1,250,000 units
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;STON.fi's own swap quickstart reads the decimal precision dynamically from asset metadata for exactly this reason.&lt;/p&gt;

&lt;p&gt;For production code, avoid converting large token values with floating-point arithmetic such as &lt;code&gt;Number(amount) * 10 ** decimals&lt;/code&gt;. A string-to-BigInt parser is safer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;whole&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;padded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;whole&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;padded&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should also reject negative amounts, malformed decimals, excessive precision, and zero before calling the API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulate before allowing the user to sign
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpffwbak1s4tjkzjnbzf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpffwbak1s4tjkzjnbzf9.png" alt="How to simulate swap on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The swap button should not construct a trade from an old displayed price or a hardcoded pool.&lt;/p&gt;

&lt;p&gt;STON.fi provides &lt;code&gt;simulateSwap&lt;/code&gt;, which lets the application calculate the swap before execution. Its REST API exposes a dedicated swap simulation endpoint for expected output, fees, and transaction-related data.&lt;/p&gt;

&lt;p&gt;A simplified request looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simulateSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;slippageTolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;0.01&lt;/code&gt; represents a 1 percent slippage tolerance.&lt;/p&gt;

&lt;p&gt;Simulation is not merely a cosmetic price preview. It connects the UI state to the transaction you will eventually build. In the current DEX v2 integration pattern, the result also supplies routing information that should be reused during transaction construction.&lt;/p&gt;

&lt;p&gt;Your quote panel should show enough information for a meaningful decision. At minimum, display:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;amount being sold&lt;/li&gt;
&lt;li&gt;expected or quoted output&lt;/li&gt;
&lt;li&gt;minimum acceptable output&lt;/li&gt;
&lt;li&gt;selected slippage tolerance&lt;/li&gt;
&lt;li&gt;source and destination assets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most importantly, clear the simulation whenever the user changes an input.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;resetQuote&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setSimulation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onAmountChange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;setAmount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;resetQuote&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Otherwise, a user can simulate 10 tokens, change the field to 100, and still see a Swap button associated with the stale 10-token result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let the STON.fi API choose the Router
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6jc5uohakab4wv6yjwy8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6jc5uohakab4wv6yjwy8.png" alt="Let the STON.fi API choose the Router" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One of the most important implementation details in the current STON.fi DEX v2 documentation is that a production application should not hardcode a Router simply because an example contract address worked previously.&lt;/p&gt;

&lt;p&gt;The recommended mainnet flow is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simulate the swap.&lt;/li&gt;
&lt;li&gt;Read the Router metadata returned by the simulation.&lt;/li&gt;
&lt;li&gt;Pass that Router metadata into &lt;code&gt;dexFactory()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Build the transaction with the resulting Router contract.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;STON.fi explicitly recommends this API-driven approach so integrations can follow Router changes without being tied to a manually embedded contract address. Its REST API currently serves mainnet data, while testnet integration requires a different, manually configured approach.&lt;/p&gt;

&lt;p&gt;The central setup is compact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://toncenter.com/api/v2/jsonRPC&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routerInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contracts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simulation and transaction should remain one logical operation. Reuse fields such as &lt;code&gt;offerUnits&lt;/code&gt;, &lt;code&gt;minAskUnits&lt;/code&gt;, token addresses, and Router metadata from the simulation rather than independently reconstructing the swap from UI values.&lt;/p&gt;

&lt;p&gt;That keeps the transaction you ask the wallet to sign aligned with the trade the interface just showed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build the right transaction for the asset pair
&lt;/h2&gt;

&lt;p&gt;STON.fi exposes different Router helpers because TON and jettons do not enter the swap through exactly the same path.&lt;/p&gt;

&lt;p&gt;Your interface therefore needs three branches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;common&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;offerAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;minAskAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minAskUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;txParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapTonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;common&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;txParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToTonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;common&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;txParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;common&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Router helper returns the information the wallet needs, including the destination, attached TON value, and message body.&lt;/p&gt;

&lt;p&gt;At the protocol level, the Router acts as the DEX entry point and directs token operations toward the appropriate pool. The pool contains the AMM state used for the swap. In DEX v2, the swap payload can also carry parameters such as minimum output, receiver, refund information, and an execution deadline.&lt;/p&gt;

&lt;p&gt;For a basic interface, you do not need to manually construct those low-level cells. That is exactly the problem the official SDK is designed to solve.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send the transaction through TON Connect
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqrrz24aenikb73oopll.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fvqrrz24aenikb73oopll.png" alt="How to send, track and verify the swap on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once &lt;code&gt;txParams&lt;/code&gt; exists, convert it into a TON Connect transaction request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;validUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is one small detail here that can prevent a surprisingly confusing bug: &lt;code&gt;validUntil&lt;/code&gt; uses a Unix timestamp in &lt;strong&gt;seconds&lt;/strong&gt;, not JavaScript milliseconds. Five minutes from now is therefore calculated with &lt;code&gt;Math.floor(Date.now() / 1000) + 300&lt;/code&gt;. TON's current TON Connect documentation defines mainnet as network &lt;code&gt;-239&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Calling &lt;code&gt;sendTransaction()&lt;/code&gt; does not expose the wallet's private key to your React application. Instead, the wallet presents the transaction to the user for approval and then signs and broadcasts it if they accept.&lt;/p&gt;

&lt;p&gt;Your UI should distinguish at least four outcomes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;waiting for wallet approval&lt;/li&gt;
&lt;li&gt;rejected by the user&lt;/li&gt;
&lt;li&gt;submitted to TON&lt;/li&gt;
&lt;li&gt;execution confirmed or failed on-chain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not interpret the successful return of &lt;code&gt;sendTransaction()&lt;/code&gt; as proof that every downstream contract action completed successfully. TON transactions can generate chains of asynchronous messages, so broadcast and final swap settlement are different stages.&lt;/p&gt;

&lt;p&gt;STON.fi exposes swap status and transaction-related API endpoints that can help an application follow the operation after submission.&lt;/p&gt;

&lt;h2&gt;
  
  
  Following one swap from input to settlement
&lt;/h2&gt;

&lt;p&gt;Consider a user opening your interface to exchange TON for a jetton.&lt;/p&gt;

&lt;p&gt;They connect a wallet through TON Connect and choose TON in the first selector. Your application loads the destination asset metadata and converts the entered TON amount into blockchain units.&lt;/p&gt;

&lt;p&gt;Next, &lt;code&gt;simulateSwap()&lt;/code&gt; asks STON.fi what the trade currently looks like. Instead of merely taking a displayed number from that result, the application stores the entire simulation object.&lt;/p&gt;

&lt;p&gt;The simulation gives the frontend the values that matter for execution, including the minimum acceptable output and Router metadata. &lt;code&gt;dexFactory()&lt;/code&gt; uses that Router description to instantiate the corresponding contracts. Because TON is the source asset, the frontend calls the TON-to-jetton Router helper and receives the prepared transaction parameters.&lt;/p&gt;

&lt;p&gt;Only then does the application open the wallet approval flow.&lt;/p&gt;

&lt;p&gt;The user's decision therefore occurs after the following chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Choose assets
   |
Enter amount
   |
Convert to base units
   |
Simulate through STON.fi API
   |
Review minimum output
   |
Create Router from simulation metadata
   |
Build swap transaction with STON.fi SDK
   |
Request signature through TON Connect
   |
Track on-chain execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is the core of a basic STON.fi swap interface. The UI is small because STON.fi's API and SDK handle much of the protocol-specific construction, but the frontend still has an important responsibility: it must preserve the relationship between what was simulated, what was displayed, and what was actually signed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes that make a basic swap unsafe or unreliable
&lt;/h2&gt;

&lt;p&gt;A prototype can appear functional while still containing several subtle integration problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardcoding the Router.&lt;/strong&gt; For current DEX v2 mainnet integrations, use Router metadata supplied by the STON.fi simulation and &lt;code&gt;dexFactory()&lt;/code&gt; instead.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Using floating-point arithmetic for token amounts.&lt;/strong&gt; Convert decimal strings into integer blockchain units using token-specific metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keeping an old quote after an input changes.&lt;/strong&gt; Clear simulation state whenever the asset pair, amount, or relevant swap setting changes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setting minimum output to an arbitrary tiny value.&lt;/strong&gt; &lt;code&gt;minAskAmount&lt;/code&gt; is the user's execution protection. Reuse the simulation result rather than replacing it with a convenient placeholder.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Treating wallet submission as final settlement.&lt;/strong&gt; A signed and broadcast TON transaction can still lead to later contract messages, failures, or refunds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sending transactions from an unidentified dApp.&lt;/strong&gt; Serve a correct TON Connect manifest from your own application domain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ignoring user rejection.&lt;/strong&gt; Declining a wallet request is a normal outcome, not an exceptional application failure. Give the user a clean way to retry.&lt;/p&gt;

&lt;p&gt;A solid first version does not need professional trading features. It needs faithful state management and a transaction that corresponds to the quote on screen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practical takeaway:&lt;/strong&gt; build the interface around the simulation object, not around the Swap button. Once a trade has been simulated, treat that result as the source for Router selection, offered units, minimum output, and transaction construction. If anything affecting the trade changes, discard the simulation and request a new one before enabling execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Do I need a backend to build a basic STON.fi swap interface?
&lt;/h3&gt;

&lt;p&gt;Not necessarily. A basic React implementation can call the STON.fi API, build the transaction with the SDK, and ask a connected wallet to sign through TON Connect directly from the frontend. A backend becomes useful for application-specific analytics, caching, access control, monitoring, or other services, but it should never require collecting the user's wallet private key.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why should a swap be simulated before execution?
&lt;/h3&gt;

&lt;p&gt;Simulation tells the application what the trade currently looks like before the wallet signs anything. It also produces values such as the minimum acceptable output and, in the current STON.fi DEX v2 workflow, Router metadata used to build the actual transaction. If inputs change after simulation, request a new simulation rather than executing the old one.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the difference between expected output and minimum received?
&lt;/h3&gt;

&lt;p&gt;Expected output describes the result indicated by the current quote or simulation. Minimum received is the lower execution boundary created by the selected slippage tolerance. If execution would produce less than that minimum, the swap should not simply proceed at any price. Your interface should make that protection visible instead of hiding it behind the Swap button.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I assume every TON token uses nine decimals?
&lt;/h3&gt;

&lt;p&gt;No. Token amounts displayed to people must be converted into integer blockchain units using that asset's own decimal metadata. Hardcoding nine decimals can make an interface submit a radically different amount for tokens with another precision. Read the metadata supplied for the selected asset and use integer-safe conversion logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I hardcode a STON.fi v2 Router address?
&lt;/h3&gt;

&lt;p&gt;Not for the recommended production mainnet flow. Current STON.fi documentation advises developers to simulate the swap first, use the Router metadata contained in that result, and instantiate the corresponding contracts through &lt;code&gt;dexFactory()&lt;/code&gt;. This reduces the chance that an integration becomes tied to an obsolete Router configuration.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does TON Connect execute the STON.fi swap itself?
&lt;/h3&gt;

&lt;p&gt;No. TON Connect is the wallet communication layer. Your application builds the STON.fi transaction, then TON Connect asks the user's wallet to approve, sign, and broadcast it. STON.fi smart contracts process the resulting on-chain messages. Keeping those roles separate makes the integration easier to reason about and prevents the frontend from handling private keys.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can I verify that a STON.fi swap actually completed?
&lt;/h3&gt;

&lt;p&gt;Do not rely only on the fact that the wallet accepted the transaction request. Treat submission and settlement as separate states. Track the resulting on-chain activity or use STON.fi transaction and swap-status facilities where appropriate. Update the interface only when you have evidence of the final result, including a possible failure or refund path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;STON.fi Swap Guide (React) - Official end-to-end example for building a React swap interface with the STON.fi API, SDK, and TON Connect&lt;/li&gt;
&lt;li&gt;STON.fi DEX v2 Swap - Current API-driven production pattern, Router discovery, &lt;code&gt;dexFactory()&lt;/code&gt;, and v2 transaction construction&lt;/li&gt;
&lt;li&gt;STON.fi REST API Reference - Swap simulation, asset queries, Router information, transaction queries, and swap status endpoints&lt;/li&gt;
&lt;li&gt;STON.fi REST API - Overview of the official HTTP interface used alongside the DEX contracts&lt;/li&gt;
&lt;li&gt;STON.fi DEX Architecture - Explanation of the Router, Pool, and contract roles involved in swaps&lt;/li&gt;
&lt;li&gt;STON.fi Router v2 Reference - Low-level swap payload fields, minimum output behavior, deadlines, routing, and refund mechanics&lt;/li&gt;
&lt;li&gt;TON Connect Get Started - Official React setup for the provider, wallet connection, manifest, and connection state&lt;/li&gt;
&lt;li&gt;TON Connect Send Transaction - Official transaction request format, &lt;code&gt;validUntil&lt;/code&gt;, network selection, message format, response, and wallet errors&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Request a Swap Quote from the STON.fi API</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Sat, 01 Aug 2026 14:01:11 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-request-a-swap-quote-from-the-stonfi-api-4kdi</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-request-a-swap-quote-from-the-stonfi-api-4kdi</guid>
      <description>&lt;p&gt;&lt;em&gt;A practical guide to simulating a TON swap, reading the returned price data, and carrying the quote safely into transaction construction.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If your application needs to ey sign a swap, STON.fi exposes a direct way to request that information: &lt;code&gt;POST https://api.ston.fi/v1/swap/simulate&lt;/code&gt;. STON.fi calls the operation a swap simulation, but in a wallet, trading interface, bot, or backend it serves the role of a swap quote. You provide the asset being sold, the asset being bought, the amount in blockchain units, and a slippage tolerance. The API returns the expected output together with minimum output, fees, price impact, gas information, pool data, and the Router that should be used if you continue to execution.&lt;/p&gt;

&lt;p&gt;The critical detail is that the quote is not just a price. It is routing and execution context for a specific swap at a specific moment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What a STON.fi swap quote actually gives you
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30f8kl5u9nho5e71vk8g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F30f8kl5u9nho5e71vk8g.png" alt="STON.fi swap quote flow" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A DEX quote answers a more useful question than "What is token A worth in token B?" It asks, "If I sell this exact amount through the liquidity available now, what should the swap produce?"&lt;/p&gt;

&lt;p&gt;STON.fi's DEX API exposes this through &lt;code&gt;/v1/swap/simulate&lt;/code&gt;. The official API reference describes the endpoint as a pre-execution simulation that calculates expected output, fees, and gas costs. The current response schema also includes &lt;code&gt;price_impact&lt;/code&gt;, &lt;code&gt;min_ask_units&lt;/code&gt;, &lt;code&gt;recommended_min_ask_units&lt;/code&gt;, &lt;code&gt;recommended_slippage_tolerance&lt;/code&gt;, pool information, and a complete &lt;code&gt;router&lt;/code&gt; object. ion matters because an AMM quote depends on the input size and pool state. Two requests for the same pair can return different results if the amount changes or if liquidity changes between requests.&lt;/p&gt;

&lt;p&gt;For a typical interface, the quote should give you enough data to display:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;expected amount received&lt;/li&gt;
&lt;li&gt;minimum acceptable amount received&lt;/li&gt;
&lt;li&gt;swap rate&lt;/li&gt;
&lt;li&gt;price impact&lt;/li&gt;
&lt;li&gt;protocol or swap fee information&lt;/li&gt;
&lt;li&gt;estimated gas parameters&lt;/li&gt;
&lt;li&gt;selected pool and Router&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A simulation does not execute anything on-chain. No wallet signature is required merely to ask the API for the quote.&lt;/p&gt;

&lt;h2&gt;
  
  
  The four inputs you need
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fufzuvmi6orr02puxno3u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fufzuvmi6orr02puxno3u.png" alt="STON.fi 4 inputs" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For a direct swap simulation, four values are essential: the asset you are selling, the asset you want to receive, the amount being sold, and the slippage tolerance. The raw REST endpoint uses snake_case query parameters, while the official TypeScript client exposes camelCase properties. The client then maps them to the REST request.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Raw REST parameter&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;@ston-fi/api&lt;/code&gt; property&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Asset to sell&lt;/td&gt;
&lt;td&gt;&lt;code&gt;offer_address&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;offerAddress&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Asset to receive&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ask_address&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;askAddress&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amount to sell&lt;/td&gt;
&lt;td&gt;&lt;code&gt;units&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;offerUnits&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Slippage tolerance&lt;/td&gt;
&lt;td&gt;&lt;code&gt;slippage_tolerance&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;slippageTolerance&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The REST endpoint also supports optional parameters such as &lt;code&gt;pool_address&lt;/code&gt;, referral settings, and DEX version restrictions. For a basic quote request, start with the four required values and add optional routing constraints only when your application has a reason to control them.&lt;/p&gt;

&lt;p&gt;One implementation detail is easy to miss: this is a &lt;code&gt;POST&lt;/code&gt; endpoint, but the documented swap inputs are query parameters. The official &lt;code&gt;@ston-fi/api&lt;/code&gt; client does the same internally when it calls &lt;code&gt;/v1/swap/simulate&lt;/code&gt;. The amount to blockchain units first&lt;/p&gt;

&lt;p&gt;&lt;code&gt;units&lt;/code&gt; does not mean a human-readable amount such as &lt;code&gt;"1.5"&lt;/code&gt; unless the token happens to use zero decimals. It means the smallest indivisible units of the offered asset.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0xeqc16cksfr78ryf4tl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0xeqc16cksfr78ryf4tl.png" alt="Blockchain units" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TON jettons can use different decimal precision. TON documentation explicitly warns developers not to assume that every jetton has the same &lt;code&gt;decimals&lt;/code&gt; value. For example, many assets use 9 decimals, while USDT on TON uses 6. An incorrect decimal conversion can change the intended amount by orders of magnitude. And is conceptually:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;blockchain units = display amount * 10^decimals&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;For production code, avoid ordinary JavaScript floating-point arithmetic for token amounts. A simple string-based conversion can keep the calculation exact:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;whole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;padded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;whole&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;
    &lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;padded&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offerUnits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;toUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.5&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "1500000000"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fetch the asset's real decimal precision from trusted metadata rather than hardcoding &lt;code&gt;9&lt;/code&gt;. If your project already uses STON.fi tooling, use the metadata returned for the selected asset and keep amounts as strings or integers until you format them for display.&lt;/p&gt;

&lt;h2&gt;
  
  
  Request the quote with the raw REST API
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffxsv9p2mi9ulik2lazdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffxsv9p2mi9ulik2lazdf.png" alt="Request the STON.fi quote" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;At the HTTP level, the request is small. You can call the production API directly with &lt;code&gt;fetch&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, or any HTTP client.&lt;/p&gt;

&lt;p&gt;A generic &lt;code&gt;curl&lt;/code&gt; request looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="s2"&gt;"https://api.ston.fi/v1/swap/simulate?offer_address=&amp;lt;OFFER_ASSET&amp;gt;&amp;amp;ask_address=&amp;lt;ASK_ASSET&amp;gt;&amp;amp;units=&amp;lt;OFFER_UNITS&amp;gt;&amp;amp;slippage_tolerance=0.01"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"accept: application/json"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In JavaScript, building the query parameters explicitly makes the request easier to inspect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offerAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;OFFER_ASSET&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;askAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;ASK_ASSET&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offerUnits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;&amp;lt;AMOUNT_IN_SMALLEST_UNITS&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;offer_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;ask_address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;units&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;slippage_tolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s2"&gt;`https://api.ston.fi/v1/swap/simulate?&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`STON.fi quote failed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;quote&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;quote&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;0.01&lt;/code&gt; value represents 1 percent slippage tolerance. STON.fi's official TypeScript client currently documents &lt;code&gt;0.01&lt;/code&gt; as a recommended value, while the simulation response can also return a &lt;code&gt;recommended_slippage_tolerance&lt;/code&gt;. Treat slippage as a transaction protection setting, not as another name for price impact. plication, wrap the call in normal network error handling, validate the response shape, and reject zero or malformed amounts before sending the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the official TypeScript client when possible
&lt;/h2&gt;

&lt;p&gt;If you are already working in TypeScript or JavaScript, &lt;code&gt;@ston-fi/api&lt;/code&gt; removes most of the raw HTTP plumbing. The package is the official TypeScript client for the STON.fi HTTP API and exposes &lt;code&gt;simulateSwap()&lt;/code&gt; directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @ston-fi/api

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;br&gt;
`&lt;/p&gt;

&lt;p&gt;Then request a quote:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`ts&lt;br&gt;
import { StonApiClient } from "@ston-fi/api";&lt;/p&gt;

&lt;p&gt;const client = new StonApiClient();&lt;/p&gt;

&lt;p&gt;const quote = await client.simulateSwap({&lt;br&gt;
  offerAddress: "",&lt;br&gt;
  askAddress: "",&lt;br&gt;
  offerUnits: "",&lt;br&gt;
  slippageTolerance: "0.01",&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;console.log({&lt;br&gt;
  expectedOutput: quote.askUnits,&lt;br&gt;
  minimumOutput: quote.minAskUnits,&lt;br&gt;
  priceImpact: quote.priceImpact,&lt;br&gt;
  swapRate: quote.swapRate,&lt;br&gt;
  router: quote.router,&lt;br&gt;
});&lt;br&gt;
&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;There is one naming difference worth remembering. The raw REST response uses fields such as &lt;code&gt;ask_units&lt;/code&gt; and &lt;code&gt;min_ask_units&lt;/code&gt;; the client normalizes API responses into camelCase, so your TypeScript code reads &lt;code&gt;askUnits&lt;/code&gt; and &lt;code&gt;minAskUnits&lt;/code&gt;. The official client source and response types make this mapping visible. applications, this client is the cleaner option because it gives you a stable application-facing interface while still using the same STON.fi REST API underneath.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the response as execution data, not just a number
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8bifcp6ah4w5z5w39bo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fq8bifcp6ah4w5z5w39bo.png" alt="How to read STON.fi response as execution data" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Suppose your UI only prints &lt;code&gt;ask_units&lt;/code&gt;. You have technically displayed an expected output, but you have thrown away much of the information that makes the quote useful.&lt;/p&gt;

&lt;p&gt;The most important raw REST fields to inspect are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;ask_units&lt;/code&gt;: the simulated output amount.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;min_ask_units&lt;/code&gt;: the minimum output associated with the supplied slippage tolerance.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;recommended_min_ask_units&lt;/code&gt;: the API's recommended minimum output.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;price_impact&lt;/code&gt;: the effect of this swap size on the execution price.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;swap_rate&lt;/code&gt;: the simulated exchange rate.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;fee_units&lt;/code&gt; and &lt;code&gt;fee_percent&lt;/code&gt;: fee information returned for the route.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gas_params&lt;/code&gt;: estimated gas-related values.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pool_address&lt;/code&gt;: the pool selected for the simulation.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;router&lt;/code&gt;: the Router metadata returned with the route.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The response type in the official client includes all of these fields. use expected output with guaranteed output.** A quote reflects a simulation against current state. If pool reserves change before the transaction executes, the final conditions can differ. That is why the minimum output and slippage protection exist.&lt;/p&gt;

&lt;p&gt;A useful quote review in your interface can therefore be compact:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"You receive" from expected output&lt;/li&gt;
&lt;li&gt;"Minimum received" from the minimum output&lt;/li&gt;
&lt;li&gt;"Price impact" as a separate risk signal&lt;/li&gt;
&lt;li&gt;fee estimate&lt;/li&gt;
&lt;li&gt;a warning when the quote is old or conditions have materially changed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If a quote is going to sit on screen for a while, request it again before constructing or submitting the transaction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Carry the returned Router into the swap
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2dz1he4c8fmhw0xysdw8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2dz1he4c8fmhw0xysdw8.png" alt="From quote to swap on STON.fi" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The most important production pattern appears after the quote is returned.&lt;/p&gt;

&lt;p&gt;STON.fi's current v2 SDK documentation explicitly recommends an API-driven workflow: simulate first, take the &lt;code&gt;router&lt;/code&gt; object from the simulation result, pass it into &lt;code&gt;dexFactory()&lt;/code&gt;, and then build the transaction against the returned Router rather than hardcoding a Router contract address. The documentation says this approach keeps integrations compatible with Router upgrades. It also states that &lt;code&gt;api.ston.fi&lt;/code&gt; serves mainnet data. off looks like this:&lt;/p&gt;

&lt;p&gt;`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;br&gt;
ts&lt;br&gt;
import { dexFactory, Client } from "@ston-fi/sdk";&lt;br&gt;
import { StonApiClient } from "@ston-fi/api";&lt;/p&gt;

&lt;p&gt;const apiClient = new StonApiClient();&lt;/p&gt;

&lt;p&gt;const simulationResult = await apiClient.simulateSwap({&lt;br&gt;
  offerAddress: "",&lt;br&gt;
  askAddress: "",&lt;br&gt;
  offerUnits: "",&lt;br&gt;
  slippageTolerance: "0.01",&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;const { router: routerInfo } = simulationResult;&lt;br&gt;
const dexContracts = dexFactory(routerInfo);&lt;/p&gt;

&lt;p&gt;const tonClient = new Client({&lt;br&gt;
  endpoint: "",&lt;br&gt;
});&lt;/p&gt;

&lt;p&gt;const router = tonClient.open(&lt;br&gt;
  dexContracts.Router.create(routerInfo.address)&lt;br&gt;
);&lt;br&gt;
&lt;code&gt;`&lt;br&gt;
`&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At that point, you have moved from "What would this swap look like?" to "Which contract configuration should build this swap?" The quote and transaction are two stages of the same workflow.&lt;/p&gt;

&lt;p&gt;STON.fi's swap documentation also recommends reusing values from the simulation result when constructing the actual transaction. That reduces the chance that your signed payload describes a different route or minimum output from the one your interface just showed. &lt;/p&gt;

&lt;h2&gt;
  
  
  Common mistakes to avoid
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc928ykszcu0s0knbxdoc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fc928ykszcu0s0knbxdoc.png" alt="Common mistakes to avoid on STON.fi swap" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Most integration bugs around quoting are not exotic smart contract failures. They are data-handling mistakes before a transaction is ever built.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Passing display amounts as **&lt;/strong&gt;&lt;code&gt;units&lt;/code&gt;*&lt;em&gt;**.&lt;/em&gt;* &lt;code&gt;"1"&lt;/code&gt; and &lt;code&gt;"1000000000"&lt;/code&gt; can represent the same human amount for a 9-decimal token, but they are very different API inputs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assuming every jetton has 9 decimals.&lt;/strong&gt; Read the token metadata. TON's jetton documentation specifically warns that decimals vary. SON body to the raw simulation endpoint and ignoring its documented query parameters.** If you call REST directly, follow the current OpenAPI schema. If you use &lt;code&gt;@ston-fi/api&lt;/code&gt;, let the client handle the mapping. ice impact and slippage as the same value.** Price impact describes how the trade affects the quoted rate through available liquidity. Slippage tolerance defines how much unfavorable movement you are willing to accept between quote and execution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardcoding the Router.&lt;/strong&gt; Use the Router returned by the simulation for the mainnet execution flow recommended by STON.fi. uote indefinitely.** A simulation is a snapshot, not a reservation. Refresh it when enough time has passed or when the amount, pair, or slippage setting changes.&lt;/p&gt;

&lt;p&gt;A good practical rule is simple: treat the quote as disposable data that must stay synchronized with the transaction you are about to ask the wallet to sign.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is &lt;code&gt;/v1/swap/simulate&lt;/code&gt; a real swap?
&lt;/h3&gt;

&lt;p&gt;No. It simulates the swap and returns expected execution data without moving funds or requiring a wallet signature. Execution is a separate step in which your application builds the appropriate TON transaction and asks the wallet to sign it. The simulation is therefore ideal for price previews, validation, and transaction preparation.&lt;/p&gt;

&lt;h3&gt;
  
  
  What does &lt;code&gt;units&lt;/code&gt; mean in the STON.fi quote request?
&lt;/h3&gt;

&lt;p&gt;It is the amount of the offered asset in its smallest blockchain units. You must convert the human-readable amount using that asset's &lt;code&gt;decimals&lt;/code&gt; metadata. For a token with 9 decimals, 1.5 tokens is 1,500,000,000 units. Do not assume every TON jetton has 9 decimals.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is slippage tolerance the same as price impact?
&lt;/h3&gt;

&lt;p&gt;No. Price impact reflects how the size of the requested swap affects the quoted execution price through pool liquidity. Slippage tolerance is the maximum adverse change your transaction is prepared to accept. STON.fi returns price impact separately and uses the slippage setting when calculating minimum output values.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I quote an exact output amount instead?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;POST /v1/reverse_swap/simulate&lt;/code&gt;. The normal &lt;code&gt;/v1/swap/simulate&lt;/code&gt; endpoint starts with a known amount to sell and estimates what you receive. The reverse endpoint starts with the amount you want to receive and calculates the required input. STON.fi exposes both flows in the REST API and in &lt;code&gt;@ston-fi/api&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I hardcode a STON.fi Router address after getting a quote?
&lt;/h3&gt;

&lt;p&gt;No for the normal mainnet integration pattern. STON.fi's current v2 documentation recommends taking the Router metadata from the simulation response and constructing the SDK contracts dynamically with &lt;code&gt;dexFactory()&lt;/code&gt;. That keeps the transaction builder aligned with the route selected by the API and avoids depending on a manually fixed Router address.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use &lt;code&gt;api.ston.fi&lt;/code&gt; to request testnet swap quotes?
&lt;/h3&gt;

&lt;p&gt;The current STON.fi v2 swap documentation states that the REST API at &lt;code&gt;api.ston.fi&lt;/code&gt; serves mainnet data. Its testnet instructions use a manual contract setup instead of the mainnet API-driven routing workflow. If you are building a production mainnet integration, use the API-driven pattern; treat testnet as a separate setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should my app check immediately before using a STON.fi quote?
&lt;/h3&gt;

&lt;p&gt;Confirm that the pair, input amount, token decimals, slippage setting, expected output, minimum output, and returned Router still match what the user sees. If the quote is stale, request a fresh simulation. Then build the transaction from that simulation data instead of reconstructing the route from hardcoded values. That keeps the visible quote and the transaction as closely aligned as possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;STON.fi DEX API Reference - endpoint overview for swaps, reverse swaps, liquidity, and DEX data&lt;/li&gt;
&lt;li&gt;STON.fi Swagger UI - interactive interface for exploring and testing the REST API&lt;/li&gt;
&lt;li&gt;STON.fi OpenAPI Schema - current machine-readable definition of &lt;code&gt;/v1/swap/simulate&lt;/code&gt;, parameters, and responses&lt;/li&gt;
&lt;li&gt;STON.fi API - official overview of the HTTP API and API viewers&lt;/li&gt;
&lt;li&gt;STON.fi v2 SDK Guide - API-driven mainnet simulation, Router discovery, and transaction construction&lt;/li&gt;
&lt;li&gt;STON.fi Swap Guide for React - end-to-end example using &lt;code&gt;@ston-fi/api&lt;/code&gt;, &lt;code&gt;@ston-fi/sdk&lt;/code&gt;, and TonConnect&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@ston-fi/api&lt;/code&gt; - official TypeScript client package and usage examples&lt;/li&gt;
&lt;li&gt;STON.fi API client source - implementation of &lt;code&gt;simulateSwap()&lt;/code&gt; and REST parameter mapping&lt;/li&gt;
&lt;li&gt;STON.fi response types - current fields returned by swap simulation in the official client&lt;/li&gt;
&lt;li&gt;TON Jetton Metadata - authoritative explanation of jetton decimals and smallest-unit conversion&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Install and Configure the STON.fi SDK</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Wed, 29 Jul 2026 06:51:27 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-install-and-configure-the-stonfi-sdk-3kia</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-install-and-configure-the-stonfi-sdk-3kia</guid>
      <description>&lt;p&gt;&lt;em&gt;Set up a TypeScript project, connect the required STON.fi and TON components, and prepare a reliable foundation for swaps and liquidity operations.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Installing the STON.fi SDK requires more than adding one npm package. The SDK creates and opens the smart contract wrappers your application needs, but a complete integration usually also requires a TON RPC client, the STON.fi API, and a wallet connection layer.&lt;/p&gt;

&lt;p&gt;For a production swap application, these components work together. The STON.fi API discovers assets, simulates the trade, and returns the correct Router metadata. The SDK converts that information into contract instances and transaction parameters. TON Connect then asks the user's wallet to approve and send the transaction.&lt;/p&gt;

&lt;p&gt;The official SDK is written for JavaScript and TypeScript applications and acts as a thin wrapper around STON.fi contracts, including Router, Pool, LP Account, Vault, and pTON contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key takeaways
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Install &lt;code&gt;@ston-fi/sdk&lt;/code&gt; together with &lt;code&gt;@ston-fi/api&lt;/code&gt; and &lt;code&gt;@ton/ton&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a TON Connect package when users will sign transactions through a wallet.&lt;/li&gt;
&lt;li&gt;Use the STON.fi API to simulate operations and discover the appropriate Router.&lt;/li&gt;
&lt;li&gt;Avoid hardcoding mainnet Router addresses in production integrations.&lt;/li&gt;
&lt;li&gt;Keep blockchain units, RPC access, wallet signing, and API data as separate layers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What the STON.fi SDK actually provides
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F72miriectojv5akxb06v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F72miriectojv5akxb06v.png" alt="STON.fi SDK Stack" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The SDK is the contract interaction layer of a STON.fi integration. It gives your application TypeScript classes and helper functions for working with STON.fi smart contracts without manually constructing cells, operation codes, and message bodies.&lt;/p&gt;

&lt;p&gt;Its main responsibilities include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;creating Router and Pool contract wrappers&lt;/li&gt;
&lt;li&gt;preparing swap transaction parameters&lt;/li&gt;
&lt;li&gt;preparing liquidity deposit and withdrawal parameters&lt;/li&gt;
&lt;li&gt;opening LP Account and Vault contracts&lt;/li&gt;
&lt;li&gt;representing pTON when the native TON asset is involved&lt;/li&gt;
&lt;li&gt;converting API Router metadata into the correct contract classes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The current v2 documentation covers newer contract functionality such as single-sided liquidity provision, Vault operations, additional pool types, and improved gas handling. The repository still includes v1 classes because existing pools and integrations may continue to use them.&lt;/p&gt;

&lt;p&gt;The SDK does not replace every other component in your application. It does not provide a token search interface, store private keys, choose a wallet for the user, or guarantee that a proposed transaction is economically suitable.&lt;/p&gt;

&lt;p&gt;A useful mental model is:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Main responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@ston-fi/api&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Assets, pools, Router metadata, simulations, and protocol data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@ston-fi/sdk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Smart contract wrappers and transaction parameters&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;@ton/ton&lt;/code&gt; or the SDK &lt;code&gt;Client&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Reading TON blockchain state through an RPC endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TON Connect&lt;/td&gt;
&lt;td&gt;Connecting a wallet and requesting transaction approval&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your application&lt;/td&gt;
&lt;td&gt;Validation, interface, error handling, and transaction monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Keeping these responsibilities separate makes the integration easier to test and upgrade.&lt;/p&gt;

&lt;h2&gt;
  
  
  Choose the right project setup
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxkoixcbm5t4zr18ssl8n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fxkoixcbm5t4zr18ssl8n.png" alt="STON.fi Project Setup" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before installing packages, decide where the SDK will run.&lt;/p&gt;

&lt;p&gt;A browser dApp normally needs the SDK, the STON.fi API client, and TON Connect. A backend service may use the SDK and a TON RPC client without TON Connect, but it then needs a separate and carefully secured signing method if it sends transactions.&lt;/p&gt;

&lt;p&gt;For a React application, a practical starting stack is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React with TypeScript&lt;/li&gt;
&lt;li&gt;Vite or Next.js&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ston-fi/sdk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ston-fi/api&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ton/ton&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@tonconnect/ui-react&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a Node.js script, bot, or backend service, you can start with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;tsx&lt;/code&gt; for local execution&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ston-fi/sdk&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ston-fi/api&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ton/ton&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not install &lt;code&gt;@ston-fi/omniston-sdk&lt;/code&gt; as a substitute for &lt;code&gt;@ston-fi/sdk&lt;/code&gt;. Omniston is a separate aggregation protocol and package. It is appropriate when your application needs aggregated or cross-DEX execution, not when the goal is direct interaction with STON.fi DEX contracts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the project and install the packages
&lt;/h2&gt;

&lt;p&gt;The following example uses React, TypeScript, and Vite because it provides a small project that is easy to inspect.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create the application
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest stonfi-sdk-starter &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;span class="nb"&gt;cd &lt;/span&gt;stonfi-sdk-starter
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the untouched project once:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Opening the starter page before adding blockchain dependencies helps separate project setup problems from SDK configuration problems.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Install the STON.fi and TON packages
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @ston-fi/sdk @ston-fi/api @ton/ton @tonconnect/ui-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official SDK installation command is &lt;code&gt;npm install @ston-fi/sdk&lt;/code&gt;. The additional packages provide API data, TON primitives, blockchain access, and wallet connection support required by a practical frontend integration.&lt;/p&gt;

&lt;p&gt;The equivalent pnpm command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm add @ston-fi/sdk @ston-fi/api @ton/ton @tonconnect/ui-react
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a backend-only TypeScript project, create a simpler environment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;stonfi-sdk-service
&lt;span class="nb"&gt;cd &lt;/span&gt;stonfi-sdk-service
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; @ston-fi/sdk @ston-fi/api @ton/ton
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; typescript tsx @types/node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add scripts to &lt;code&gt;package.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsx src/index.ts"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"typecheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc --noEmit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tsc"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Package versions should normally be committed through your lockfile. Avoid copying old version numbers from tutorials because SDK examples can change when Router classes, factory helpers, or peer dependencies are updated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure TypeScript and the browser runtime
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft6hu2tsxug4341o8fzlu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft6hu2tsxug4341o8fzlu.png" alt="STON.fi TypeScript, Vite, and env setup" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The STON.fi SDK is designed for TypeScript, so strict compiler settings are useful. They catch incorrect addresses, missing transaction fields, and incompatible contract types before runtime.&lt;/p&gt;

&lt;p&gt;A Vite React project already includes a suitable TypeScript configuration. For a standalone Node.js project, you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ES2022"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NodeNext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"moduleResolution"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NodeNext"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"resolveJsonModule"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"src"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling browser polyfills
&lt;/h3&gt;

&lt;p&gt;TON libraries may use Node-compatible primitives such as &lt;code&gt;Buffer&lt;/code&gt;. Some browser bundlers provide the required compatibility automatically, while others need an explicit polyfill.&lt;/p&gt;

&lt;p&gt;For Vite, install:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; vite-plugin-node-polyfills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update &lt;code&gt;vite.config.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nodePolyfills&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite-plugin-node-polyfills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;nodePolyfills&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official STON.fi React quickstart uses a Buffer polyfill in its Vite configuration. Add it when your build reports that &lt;code&gt;Buffer&lt;/code&gt; is undefined or cannot be resolved, rather than adding unrelated Node polyfills without a reason.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add environment variables
&lt;/h3&gt;

&lt;p&gt;Create &lt;code&gt;.env.local&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_TON_RPC_ENDPOINT=https://toncenter.com/api/v2/jsonRPC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a type declaration in &lt;code&gt;src/vite-env.d.ts&lt;/code&gt; if your project does not already provide one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;/// &amp;lt;reference types="vite/client" /&amp;gt;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ImportMetaEnv&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;VITE_TON_RPC_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ImportMeta&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ImportMetaEnv&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anything prefixed with &lt;code&gt;VITE_&lt;/code&gt; becomes visible in the browser bundle. Never place a private key, wallet mnemonic, or secret RPC credential in a Vite environment variable.&lt;/p&gt;

&lt;p&gt;A public frontend can use a public endpoint or a restricted browser-safe credential. Sensitive API keys belong on a backend that your frontend accesses through controlled application endpoints.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configure the blockchain and STON.fi clients
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffovv29dei1ytt3f9oetz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffovv29dei1ytt3f9oetz.png" alt="Configure the core STON.fi clients" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;src/lib/stonfi.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;endpoint&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_TON_RPC_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;VITE_TON_RPC_ENDPOINT is not configured&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stonApiClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These two clients solve different problems.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Client&lt;/code&gt; opens contract wrappers and reads data from TON through the configured RPC endpoint. &lt;code&gt;StonApiClient&lt;/code&gt; talks to the STON.fi HTTP API and requires no configuration for its standard public endpoint. The API client can retrieve assets, pools, Routers, wallet positions, and simulation results.&lt;/p&gt;

&lt;p&gt;Keeping both instances in one module prevents every component from creating its own client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Discover the Router dynamically
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5hbv2cv7j6s5zng1py03.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5hbv2cv7j6s5zng1py03.png" alt="Build STON.fi Router" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Older examples often instantiate a specific Router class or copy a known contract address. That can work for controlled tests, but production applications should not assume that every asset pair uses the same Router version or pool type.&lt;/p&gt;

&lt;p&gt;The current mainnet-first pattern is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask the STON.fi API to simulate the operation.&lt;/li&gt;
&lt;li&gt;Read the Router metadata returned by the simulation.&lt;/li&gt;
&lt;li&gt;Pass that metadata into &lt;code&gt;dexFactory()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Open the generated Router contract with the blockchain client.&lt;/li&gt;
&lt;li&gt;Build transaction parameters from the same simulation values.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create &lt;code&gt;src/lib/prepareSwap.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;dexFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stonApiClient&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./stonfi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PrepareSwapInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;slippageTolerance&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;prepareSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;slippageTolerance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;PrepareSwapInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stonApiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simulateSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;slippageTolerance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routerInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contracts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The simulation result includes values such as the offered asset, requested asset, offered units, protected minimum output, and Router information. Reusing those values helps ensure that the transaction being constructed matches the route the application displayed to the user.&lt;/p&gt;

&lt;p&gt;This file deliberately stops before building or sending a transaction. Installation and configuration should first prove that API access, Router discovery, contract creation, and TypeScript compilation all work.&lt;/p&gt;

&lt;h3&gt;
  
  
  Work with integer blockchain units
&lt;/h3&gt;

&lt;p&gt;Do not pass human-readable decimal values directly into contract methods unless a specific helper explicitly accepts them.&lt;/p&gt;

&lt;p&gt;A token interface might display &lt;code&gt;1.25&lt;/code&gt;, but the blockchain operation needs an integer based on that token's decimals. A token with six decimals represents &lt;code&gt;1.25&lt;/code&gt; as &lt;code&gt;1250000&lt;/code&gt; units, while a token with nine decimals represents it as &lt;code&gt;1250000000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The asset metadata should determine the conversion. Avoid assuming that every jetton uses nine decimals.&lt;/p&gt;

&lt;p&gt;Also avoid normal JavaScript floating-point arithmetic for financial amounts. Convert the user's string input into integer units, keep transaction amounts as strings or &lt;code&gt;bigint&lt;/code&gt;, and only format them back into decimals for display.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add TON Connect for wallet approval
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F22cj2tquhk9d8bbq7gs2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F22cj2tquhk9d8bbq7gs2.png" alt="TON connect STON.fi wallet flow" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The SDK prepares transaction parameters, but it should not receive a user's seed phrase or private key in a normal browser dApp. TON Connect provides the wallet connection and approval layer.&lt;/p&gt;

&lt;p&gt;Create &lt;code&gt;public/tonconnect-manifest.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-domain.example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STON.fi SDK Starter"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iconUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-domain.example/icon-180.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, the manifest must be available through a public HTTPS URL. The wallet retrieves it to display the application's identity during connection. The icon should use a wallet-supported format such as PNG.&lt;/p&gt;

&lt;p&gt;Wrap the application in &lt;code&gt;src/main.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StrictMode&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRoot&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectUIProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;
      &lt;span class="na"&gt;manifestUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tonconnect-manifest.json`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add a connection button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;WalletButton&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TON Connect is the standard wallet connection protocol for TON dApps. It lets an application read the connected address and request transaction approval without taking possession of the wallet's keys. It does not replace the STON.fi SDK or the blockchain data client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify the installation before building a swap
&lt;/h2&gt;

&lt;p&gt;A useful first test is an API request that does not send a transaction.&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;src/App.tsx&lt;/code&gt; temporarily:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;stonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./lib/stonfi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Not tested&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;testConfiguration&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading STON.fi assets...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stonApiClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getAssets&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;STON.fi asset response:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SDK environment is configured&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Configuration test failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;STON.fi SDK Starter&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;testConfiguration&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Test configuration
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the checks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The development server proves that the browser can load the modules. The production build is equally important because missing polyfills, module resolution problems, and environment variable mistakes sometimes appear only during bundling.&lt;/p&gt;

&lt;p&gt;Before continuing, confirm that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the application compiles without TypeScript errors&lt;/li&gt;
&lt;li&gt;the asset request returns a response&lt;/li&gt;
&lt;li&gt;the wallet connection button opens&lt;/li&gt;
&lt;li&gt;the manifest loads from its expected URL&lt;/li&gt;
&lt;li&gt;no private data appears in the frontend bundle&lt;/li&gt;
&lt;li&gt;the production build completes successfully&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Common configuration mistakes and production checks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fosausnbhfrb5u7dv9hen.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fosausnbhfrb5u7dv9hen.png" alt="Preflight STON.fi checks and common mistakes" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One frequent mistake is treating the STON.fi API and the SDK as interchangeable. The API provides indexed data and simulations. The SDK creates smart contract objects and transaction messages. A production application normally needs both.&lt;/p&gt;

&lt;p&gt;Another problem is mixing examples from different SDK generations. A v1 example may use &lt;code&gt;DEX.v1.Router&lt;/code&gt;, while a current v2 workflow can use API Router metadata and &lt;code&gt;dexFactory()&lt;/code&gt;. Check the documentation section and package version before copying a method name.&lt;/p&gt;

&lt;p&gt;Watch for these additional issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hardcoded Router addresses:&lt;/strong&gt; Resolve the mainnet Router from API metadata whenever possible.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mainnet and testnet mixing:&lt;/strong&gt; The public STON.fi API serves mainnet data, so its Router information should not be combined with testnet assets or contracts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unsafe decimal arithmetic:&lt;/strong&gt; Convert display amounts into integer token units before simulation or transaction construction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exposed secrets:&lt;/strong&gt; Never place mnemonics, private keys, or unrestricted API credentials in browser code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing simulation:&lt;/strong&gt; Generate and review a current simulation before constructing the transaction.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unverified token addresses:&lt;/strong&gt; Symbols and names can be duplicated, so use verified asset addresses and metadata.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No expiration strategy:&lt;/strong&gt; Transaction requests should not remain valid indefinitely.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No post-transaction tracking:&lt;/strong&gt; A wallet acceptance response is not the same as confirmed on-chain execution.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A production-ready project should also log operation identifiers, display the minimum protected output, handle RPC and API timeouts, prevent duplicate submissions, and explain wallet rejection separately from blockchain failure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Practical takeaway
&lt;/h3&gt;

&lt;p&gt;A correct STON.fi SDK installation has four working layers: the STON.fi API can return current protocol data, the TON client can open the dynamically selected contracts, the SDK can build typed transaction parameters, and TON Connect can request wallet approval. Test each layer independently before combining them into a real swap. That approach makes configuration errors easier to identify and reduces the risk of signing a transaction built from stale or mismatched data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is the STON.fi SDK only for TypeScript?
&lt;/h3&gt;

&lt;p&gt;The SDK is written in TypeScript but can also be imported into JavaScript projects. TypeScript is preferable because contract methods contain many address, amount, and configuration fields that benefit from static checking. Even in a JavaScript application, the package's included type declarations can improve editor suggestions and reveal incorrect method usage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need &lt;code&gt;@ston-fi/api&lt;/code&gt; to use &lt;code&gt;@ston-fi/sdk&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Not for every low-level operation, but it is strongly recommended for production applications. The API provides asset information, pool data, simulations, and Router metadata. Without it, you may need to hardcode contract information and independently calculate or retrieve values that the API already exposes in a consistent format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why should I install &lt;code&gt;@ton/ton&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;The STON.fi SDK is built around TON contract primitives and blockchain client behavior. The &lt;code&gt;@ton/ton&lt;/code&gt; package provides core types and utilities used across TON integrations. Installing it explicitly also helps the package manager resolve compatible peer dependencies and makes TON-specific imports available to the rest of your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should a new integration use STON.fi v1 or v2?
&lt;/h3&gt;

&lt;p&gt;A new integration should normally begin with the current v2 documentation and an API-driven Router selection flow. However, the Router returned for a particular operation should determine the contract classes your application opens. Do not force every operation through a manually selected version when &lt;code&gt;dexFactory()&lt;/code&gt; can interpret the Router metadata.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can the STON.fi SDK be tested on TON testnet?
&lt;/h3&gt;

&lt;p&gt;Yes, but testnet configuration is more manual. The public STON.fi API provides mainnet protocol data, so its simulations and Router metadata should not be reused for testnet transactions. Testnet development may require known test contracts, suitable jettons, funded wallets, and pools with enough liquidity to exercise the intended operation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does Vite report that &lt;code&gt;Buffer&lt;/code&gt; is undefined?
&lt;/h3&gt;

&lt;p&gt;Some TON dependencies use Node-compatible binary utilities, while browsers do not provide every Node global automatically. In a Vite project, adding &lt;code&gt;vite-plugin-node-polyfills&lt;/code&gt; and enabling the Buffer polyfill usually resolves this specific issue. Add only the compatibility features your build needs rather than exposing a complete Node environment in the browser.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does the SDK connect to the user's wallet?
&lt;/h3&gt;

&lt;p&gt;No. The SDK prepares contract calls and transaction parameters. TON Connect, a wallet-specific SDK, or another signer sends those parameters for approval. In a standard non-custodial frontend, TON Connect allows the wallet to sign without revealing private keys to your application.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the minimum reliable setup for a STON.fi swap?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;@ston-fi/api&lt;/code&gt; to simulate the swap, take the Router metadata from that result, pass it to &lt;code&gt;dexFactory()&lt;/code&gt;, open the Router through the configured TON client, and generate transaction parameters from the simulated amounts. Finally, send those parameters through TON Connect and monitor the resulting on-chain operation instead of treating wallet approval as final settlement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;STON.fi DEX SDK documentation - Installation, supported SDK generations, and links to version-specific contract guides&lt;/li&gt;
&lt;li&gt;STON.fi SDK v2 swap documentation - API-driven Router discovery, &lt;code&gt;dexFactory()&lt;/code&gt;, simulation data, and transaction preparation&lt;/li&gt;
&lt;li&gt;STON.fi React swap quickstart - Complete frontend setup using the SDK, STON.fi API, TON Connect, Vite, and browser polyfills&lt;/li&gt;
&lt;li&gt;STON.fi SDK GitHub repository - Source code, package structure, supported contract wrappers, and the official Next.js demo application&lt;/li&gt;
&lt;li&gt;STON.fi API GitHub repository - Installation, zero-configuration client setup, and examples for assets, pools, Routers, farms, and operations&lt;/li&gt;
&lt;li&gt;STON.fi SDK npm package - Published package information and the official installation command&lt;/li&gt;
&lt;li&gt;TON Connect getting started guide - Manifest requirements, React packages, provider configuration, and wallet connection setup&lt;/li&gt;
&lt;li&gt;TON Connect overview - Wallet connection architecture, available packages, and the separation between wallet communication and blockchain integration&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How to Integrate STON.fi Swaps with the TypeScript SDK</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Tue, 28 Jul 2026 06:55:06 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-to-integrate-stonfi-swaps-with-the-typescript-sdk-59lo</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-to-integrate-stonfi-swaps-with-the-typescript-sdk-59lo</guid>
      <description>&lt;p&gt;&lt;em&gt;Build a production-minded swap flow with the STON.fi API, SDK v2, React, and TON Connect.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Integrating a STON.fi swap is not just a matter of calling one SDK function. A reliable application first requests a simulation from the STON.fi API, uses the returned routing information to select the correct smart contracts, builds the transaction through the TypeScript SDK, and finally asks the connected wallet to sign it through TON Connect.&lt;/p&gt;

&lt;p&gt;The SDK never needs access to a seed phrase or private key. It prepares the blockchain message, while the wallet remains responsible for authorization and broadcasting. That separation lets you add non-custodial swaps to a wallet, Telegram Mini App, game, payment interface, or DeFi dashboard without taking custody of user funds.&lt;/p&gt;

&lt;h2&gt;
  
  
  The integration has four separate layers
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fapm6fnov4kcmcutzi0tr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fapm6fnov4kcmcutzi0tr.png" alt="The STON.fi integration has four separate layers" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A common source of confusion is treating the STON.fi SDK as a complete swapping service. It is more accurate to think of the integration as a pipeline with four components.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Main responsibility&lt;/th&gt;
&lt;th&gt;Signs transactions?&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@ston-fi/api&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Loads assets, simulates swaps, and returns routing metadata&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@ston-fi/sdk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates the correct Router, pTON, and transaction parameters&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TON RPC client&lt;/td&gt;
&lt;td&gt;Reads contract data and opens contract wrappers&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;TON Connect&lt;/td&gt;
&lt;td&gt;Sends the prepared message to the connected wallet&lt;/td&gt;
&lt;td&gt;The wallet does&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The STON.fi API should normally be the starting point. Its simulation response includes the expected amounts, minimum protected output, asset addresses, and the complete Router object. You pass that Router object to &lt;code&gt;dexFactory()&lt;/code&gt;, which selects the correct contract implementation for the route.&lt;/p&gt;

&lt;p&gt;This API-driven approach is safer than copying a Router address from an old tutorial. STON.fi supports different Router versions and contract types, so an address or class that works for one pool may not be suitable for another. The official v2 documentation recommends allowing the simulation response to dictate which Router should be used.&lt;/p&gt;

&lt;p&gt;The complete flow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Connect a wallet with TON Connect.&lt;/li&gt;
&lt;li&gt;Select the offer and ask assets.&lt;/li&gt;
&lt;li&gt;Convert the entered amount into blockchain units.&lt;/li&gt;
&lt;li&gt;Simulate the swap through &lt;code&gt;@ston-fi/api&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Create the correct DEX contracts with &lt;code&gt;dexFactory()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Build the appropriate swap transaction parameters.&lt;/li&gt;
&lt;li&gt;Send the generated message through TON Connect.&lt;/li&gt;
&lt;li&gt;Track the submitted transaction separately.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Set up the TypeScript project
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdmq306mw37cy6y2wqxjo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdmq306mw37cy6y2wqxjo.png" alt="How to set up the STON.fi TypeScript project" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The examples below use React and Vite, but the same SDK flow works with Next.js, Vue, Svelte, a Telegram Mini App, or a backend service that only prepares unsigned transaction messages.&lt;/p&gt;

&lt;p&gt;Install the required packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @ston-fi/sdk @ston-fi/api @tonconnect/ui-react @ton/ton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a Vite application, you may also need a browser polyfill for &lt;code&gt;Buffer&lt;/code&gt;, which TON libraries use when serializing a cell into a base64 Bag of Cells, or BoC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; vite-plugin-node-polyfills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A minimal Vite configuration can expose only the required &lt;code&gt;buffer&lt;/code&gt; polyfill:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// vite.config.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nodePolyfills&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite-plugin-node-polyfills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;nodePolyfills&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official STON.fi quickstart uses the SDK for transaction construction, the API client for asset discovery and simulation, and TON Connect UI for wallet communication.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect the wallet without handling private keys
&lt;/h2&gt;

&lt;p&gt;Wrap the application with &lt;code&gt;TonConnectUIProvider&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/main.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectUIProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;
      &lt;span class="na"&gt;manifestUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tonconnect-manifest.json`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create &lt;code&gt;public/tonconnect-manifest.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-app.example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STON.fi Swap Demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iconUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-app.example/icon.png"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use your real production domain and a publicly accessible icon before deployment. The wallet reads this manifest to identify the application requesting a connection.&lt;/p&gt;

&lt;p&gt;Inside the swap component, add the wallet button and hooks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;TonConnectButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SwapPanel&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userAddress&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connect a wallet to continue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TON Connect creates an encrypted connection between the application and wallet. Your application can read the connected address and request a transaction, but it does not receive the wallet's private key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat token amounts as integer units
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flj09dkfl5wvav0jd7zi0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flj09dkfl5wvav0jd7zi0.png" alt="STON.fi token amounts and decimals" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Smart contracts do not receive values such as &lt;code&gt;1.25&lt;/code&gt; directly. They receive integers expressed in the asset's smallest units.&lt;/p&gt;

&lt;p&gt;An asset with nine decimals represents &lt;code&gt;1.25&lt;/code&gt; as &lt;code&gt;1250000000&lt;/code&gt;. An asset with six decimals represents the same displayed amount as &lt;code&gt;1250000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Do not automatically apply &lt;code&gt;toNano()&lt;/code&gt; to every jetton. That helper assumes nine decimals, while some TON assets use another precision. The SDK provides decimal-aware utilities, and the STON.fi API also supplies token metadata that your interface can use.&lt;/p&gt;

&lt;p&gt;A small string-based parser avoids the rounding problems that can occur when a decimal amount is first converted to a JavaScript &lt;code&gt;number&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;contractAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Jetton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;symbol&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;parseUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;(\.\d&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)?&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter a valid positive decimal amount&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;whole&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fraction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;normalized&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fraction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`This asset supports no more than &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; decimal places`&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;units&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;whole&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;fraction&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;padEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sr"&gt;/^0+&lt;/span&gt;&lt;span class="se"&gt;(?=\d)&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;""&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;units&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getApiAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;asset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The user-facing name of the native network coin may be displayed as Gram, but current contract and API identifiers can still contain names such as &lt;code&gt;Ton&lt;/code&gt;, &lt;code&gt;"ton"&lt;/code&gt;, and &lt;code&gt;pTON&lt;/code&gt;. Those values are part of the integration interface and should not be replaced with display labels.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simulate the swap before building anything
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbd6hlb1cmml8xdycdswc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbd6hlb1cmml8xdycdswc.png" alt="Simulate STON.fi swap first" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Simulation is the quote stage. It tells the application which route is available and provides the values needed to create a protected transaction.&lt;/p&gt;

&lt;p&gt;Initialize the API client and request a simulation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;simulateStonSwap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;amount&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;contractAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Select two different assets&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;offerUnits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseUnits&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;decimals&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;BigInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The swap amount must be greater than zero&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simulateSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getApiAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;getApiAddress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;slippageTolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, &lt;code&gt;"0.01"&lt;/code&gt; represents a 1 percent slippage tolerance. It is an example rather than a universal recommendation. Your interface should explain the setting and allow the product to choose an appropriate default.&lt;/p&gt;

&lt;p&gt;Several fields from the response are especially important:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;offerUnits&lt;/code&gt; is the input amount in blockchain units.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;minAskUnits&lt;/code&gt; is the minimum protected amount that the transaction may accept.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;offerAddress&lt;/code&gt; and &lt;code&gt;askAddress&lt;/code&gt; identify the assets used by the route.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;router&lt;/code&gt; contains the version and contract information required by the SDK.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not calculate &lt;code&gt;minAskUnits&lt;/code&gt; independently after receiving a simulation. Use the value returned for that exact quote. If the amount, assets, or slippage setting changes, discard the previous simulation and request a new one.&lt;/p&gt;

&lt;p&gt;A production interface should display the expected output as well as the minimum protected output. These values answer different questions: expected output describes the estimate, while minimum output defines the transaction's on-chain protection.&lt;/p&gt;

&lt;p&gt;STON.fi's current v2 workflow is mainnet-first. Its public REST API supplies mainnet routing data, so it should not be combined with a testnet RPC endpoint or testnet wallet when constructing a real swap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let &lt;code&gt;dexFactory()&lt;/code&gt; select the Router
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2zwgtwi3uf5s14m232fu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2zwgtwi3uf5s14m232fu.png" alt="Right STON.fi swap transaction" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After simulation, avoid manually choosing &lt;code&gt;DEX.v2_1&lt;/code&gt;, &lt;code&gt;DEX.v2_2&lt;/code&gt;, a constant-product Router, or another contract class. Feed the returned Router information into &lt;code&gt;dexFactory()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting factory output contains contract classes compatible with that Router, including the appropriate pTON implementation when the native coin participates in the route.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dexFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SwapSimulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;Awaited&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;
  &lt;span class="nb"&gt;ReturnType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;simulateSwap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BuildSwapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapSimulation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;rpcEndpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildStonSwapMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;rpcEndpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;BuildSwapParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;rpcEndpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routerInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;dex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;commonParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;offerAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;minAskAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minAskUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapTonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;commonParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToTonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;commonParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapJettonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;commonParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;offerJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The three branches exist because the native coin is not a jetton. STON.fi uses a compatible pTON contract when the route begins or ends with the native asset. A jetton-to-jetton swap does not require that parameter.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dexFactory()&lt;/code&gt; also protects the integration from a broader compatibility problem. New Router and pool types do not always expose identical contract behavior. Selecting a generic or hardcoded class may compile while still producing a transaction that fails for a specific route.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send the generated message through TON Connect
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1to4lp2nz1am0198rtq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1to4lp2nz1am0198rtq2.png" alt="Send STON.fi through TON connect" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The SDK returns transaction parameters containing three values your wallet request needs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;to&lt;/code&gt;, the destination contract address&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;value&lt;/code&gt;, the native amount attached for execution and gas&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;body&lt;/code&gt;, the serialized contract payload&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Convert the body to a base64 BoC and send it through TON Connect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SendSwapParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapSimulation&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SwapAsset&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;rpcEndpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;validUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;network&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="nl"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="nl"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;boc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sendStonSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;rpcEndpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;SendSwapParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;buildStonSwapMessage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;fromAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;toAsset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;userAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;rpcEndpoint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;
    &lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The SDK did not create a transaction payload&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;validUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;boc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;validUntil&lt;/code&gt; must be a Unix timestamp in seconds. Adding 300 gives the user five minutes to review the wallet request. Passing &lt;code&gt;Date.now() + 300000&lt;/code&gt; would produce milliseconds instead of seconds and should be avoided.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;network&lt;/code&gt; value &lt;code&gt;"-239"&lt;/code&gt; identifies TON mainnet. Setting the network explicitly helps prevent a mainnet transaction from being submitted through a wallet connected to another network.&lt;/p&gt;

&lt;p&gt;A resolved &lt;code&gt;sendTransaction()&lt;/code&gt; call means the wallet accepted and broadcast the signed external message. It does not prove that every subsequent smart contract message completed successfully. Save the returned BoC or another correlation identifier and use a blockchain indexer, explorer service, or backend reconciliation process to determine the final result.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production checks that prevent expensive mistakes
&lt;/h2&gt;

&lt;p&gt;A demo can stop after opening the wallet. A production integration needs stronger validation, state management, and transaction tracking.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Invalidate stale simulations.&lt;/strong&gt; Clear the simulation whenever the amount, token pair, wallet, or slippage setting changes. Consider requesting a fresh simulation immediately before opening the wallet.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep decimal handling asset-specific.&lt;/strong&gt; Read decimals from verified asset metadata and use integer or string arithmetic. Do not convert large blockchain-unit values through JavaScript floating-point numbers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Do not hardcode Router and pTON addresses.&lt;/strong&gt; Use &lt;code&gt;simulation.router&lt;/code&gt;, &lt;code&gt;dexFactory()&lt;/code&gt;, and the Router's &lt;code&gt;ptonMasterAddress&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep the network consistent.&lt;/strong&gt; The STON.fi API route, RPC endpoint, connected wallet, and transaction request must all refer to mainnet for the production DEX flow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validate the wallet request.&lt;/strong&gt; Before calling TON Connect, verify that the destination, attached amount, and payload came from the current SDK result rather than from editable form data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Distinguish rejection from execution failure.&lt;/strong&gt; A user can close the wallet prompt, a request can expire, an RPC call can fail, or the on-chain route can fail after broadcasting. These outcomes need different interface messages.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Protect infrastructure credentials.&lt;/strong&gt; Do not expose a privileged RPC key in a public frontend bundle. Use a restricted browser-safe endpoint or proxy sensitive infrastructure through your backend.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Test the complete route matrix.&lt;/strong&gt; Exercise Gram-to-jetton, jetton-to-Gram, and jetton-to-jetton swaps. Also test assets with different decimals, small balances, insufficient gas, stale simulations, wallet rejection, and invalid token pairs.&lt;/p&gt;

&lt;p&gt;The most useful first production exercise is a minimal swap with a limited amount. Log the simulation response, selected Router type, generated destination, attached value, returned BoC, and final on-chain result. Once that lifecycle is reliable, connect it to the rest of your application rather than debugging the complete product and swap flow at the same time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Does the STON.fi TypeScript SDK perform the swap by itself?
&lt;/h3&gt;

&lt;p&gt;No. The SDK creates contract wrappers and transaction parameters, but it does not sign on behalf of the wallet holder. Your application passes the generated destination, amount, and payload to TON Connect. The connected wallet displays the request, receives authorization from its owner, signs it, and broadcasts it to TON.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does the application need to simulate the swap first?
&lt;/h3&gt;

&lt;p&gt;Simulation returns more than an output estimate. It supplies the minimum protected output, asset addresses, and Router metadata needed to build the correct transaction. Without a current simulation, the application may use an outdated price, an incompatible contract, or a minimum output that no longer reflects current pool conditions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I hardcode the STON.fi Router address?
&lt;/h3&gt;

&lt;p&gt;You technically can for a tightly controlled contract integration, but it is not the recommended production pattern. STON.fi routes can use different Router versions and types. Using &lt;code&gt;simulation.router&lt;/code&gt; with &lt;code&gt;dexFactory()&lt;/code&gt; lets the API select the contracts compatible with the current route and reduces maintenance when the protocol introduces new contract implementations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should I use &lt;code&gt;toNano()&lt;/code&gt; for every swap amount?
&lt;/h3&gt;

&lt;p&gt;No. &lt;code&gt;toNano()&lt;/code&gt; assumes nine decimal places. That is correct for the native coin and many jettons, but not for every asset. Read the asset's decimals from metadata and convert the displayed value into integer units accordingly. Incorrect precision can make the submitted amount much larger or smaller than the amount shown in your interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  How should slippage be handled in the interface?
&lt;/h3&gt;

&lt;p&gt;Treat slippage as a visible product setting rather than a hidden constant. Explain that it affects &lt;code&gt;minAskUnits&lt;/code&gt;, validate the permitted range, and request a new simulation whenever it changes. Extremely loose tolerance can expose the swap to an unexpectedly poor result, while extremely tight tolerance can cause execution to fail as pool conditions move.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I test the same API-driven swap flow on TON testnet?
&lt;/h3&gt;

&lt;p&gt;Not directly with production routing data. The current STON.fi REST API workflow described in the v2 documentation serves mainnet routes. Combining its simulation result with a testnet RPC endpoint or testnet wallet creates a network mismatch. Separate unit tests and message-building tests from small, carefully reviewed mainnet integration tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does a successful TON Connect response mean the swap finished?
&lt;/h3&gt;

&lt;p&gt;No. The response confirms that the wallet created and broadcast the signed external message. TON processes smart contract messages asynchronously, so the application should still verify the resulting on-chain activity. Store the returned BoC or another tracking identifier and update the interface only after your monitoring layer determines the final outcome.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should I verify before enabling STON.fi swaps for real users?
&lt;/h3&gt;

&lt;p&gt;Verify token addresses and decimals, all three swap directions, Router selection, pTON compatibility, quote invalidation, mainnet configuration, wallet rejection, request expiration, insufficient gas, and final transaction tracking. Start with limited values and review the complete message lifecycle before allowing larger transactions or connecting swaps to automated product actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;STON.fi SDK overview - installation, SDK versions, and available DEX capabilities&lt;/li&gt;
&lt;li&gt;STON.fi Swap v2 guide - API-driven Router selection and the mainnet-first transaction flow&lt;/li&gt;
&lt;li&gt;STON.fi Swap Quickstart - complete React example using the API, SDK, and TON Connect&lt;/li&gt;
&lt;li&gt;STON.fi SDK GitHub repository - official TypeScript source code and Next.js demonstration application&lt;/li&gt;
&lt;li&gt;STON.fi SDK changelog - Router types, &lt;code&gt;dexFactory()&lt;/code&gt;, contract migrations, and decimal-aware utilities&lt;/li&gt;
&lt;li&gt;STON.fi API GitHub repository - official TypeScript client for assets, pools, simulations, and Router information&lt;/li&gt;
&lt;li&gt;TON Connect transaction guide - current request format, Unix expiration time, network selection, and returned BoC&lt;/li&gt;
&lt;li&gt;TON Connect overview - wallet connection architecture and private-key separation&lt;/li&gt;
&lt;li&gt;STON.fi integration article - official overview of adding swaps to a React application&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>How Do You Connect a TON Wallet to STON.fi?</title>
      <dc:creator>Ivan “Crypto Vazima” Zimanov</dc:creator>
      <pubDate>Sat, 11 Jul 2026 09:16:31 +0000</pubDate>
      <link>https://dev.to/ivan_cryptovazimazima/how-do-you-connect-a-ton-wallet-to-stonfi-1oh8</link>
      <guid>https://dev.to/ivan_cryptovazimazima/how-do-you-connect-a-ton-wallet-to-stonfi-1oh8</guid>
      <description>&lt;p&gt;Build a React wallet connection with TON Connect, read the connected account, and pass STON.fi transactions to the wallet for approval.&lt;/p&gt;

&lt;p&gt;Connecting a TON wallet to STON.fi does not require importing a private key or giving an application control over the wallet. The connection is created through TON Connect, the standard wallet communication protocol for TON.&lt;/p&gt;

&lt;p&gt;For someone using the official STON.fi interface, the process is simple: open the application, select &lt;strong&gt;Connect Wallet&lt;/strong&gt;, choose a compatible wallet, and approve the connection. For developers, the same process can be integrated into a React application with &lt;code&gt;@tonconnect/ui-react&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once connected, the application can read the public wallet address and request transactions. The wallet still holds the private keys and asks the owner to approve every transaction.&lt;/p&gt;

&lt;p&gt;This tutorial builds that connection and then demonstrates how it fits into a STON.fi swap integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you will build
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F13xa52t2wjrfqonis4ju.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F13xa52t2wjrfqonis4ju.png" alt="How Wallet Connection Works on STON.fi" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By the end of the tutorial, the application will be able to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Display a TON Connect wallet selector.&lt;/li&gt;
&lt;li&gt;Restore an existing wallet session after a page reload.&lt;/li&gt;
&lt;li&gt;Read the connected wallet address and network.&lt;/li&gt;
&lt;li&gt;Reject a testnet wallet when the application targets mainnet.&lt;/li&gt;
&lt;li&gt;Request STON.fi swap data through the official API.&lt;/li&gt;
&lt;li&gt;Build a STON.fi transaction with the SDK.&lt;/li&gt;
&lt;li&gt;Send the transaction to the connected wallet for approval.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The integration uses three separate layers:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Layer&lt;/th&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wallet connection&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@tonconnect/ui-react&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Opens the wallet selector and manages the session&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STON.fi data&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@ston-fi/api&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Retrieves assets, pools, simulations, and routing data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;STON.fi transactions&lt;/td&gt;
&lt;td&gt;&lt;code&gt;@ston-fi/sdk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Builds the transaction parameters sent to the wallet&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The wallet connection and the DEX integration are related, but they serve different purposes. TON Connect communicates with the wallet. The STON.fi API and SDK prepare the operation that the wallet will sign.&lt;/p&gt;

&lt;h2&gt;
  
  
  What connecting a wallet actually authorizes
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo98a2ctne5z5paxsx0gd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fo98a2ctne5z5paxsx0gd.png" alt="Integration Architecture for STON.fi" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A wallet connection is not a token approval and does not move funds.&lt;/p&gt;

&lt;p&gt;After the user approves the connection, the application normally receives information such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The selected TON account address.&lt;/li&gt;
&lt;li&gt;The network used by the account.&lt;/li&gt;
&lt;li&gt;The wallet application name.&lt;/li&gt;
&lt;li&gt;Supported wallet features.&lt;/li&gt;
&lt;li&gt;A session that can be restored later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The application may then prepare a transaction and send a signing request. The wallet displays that request separately, allowing the user to review and reject it.&lt;/p&gt;

&lt;p&gt;A secure integration should therefore treat these as two distinct events:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Connect:&lt;/strong&gt; establish a communication session and obtain the public address.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transact:&lt;/strong&gt; ask the wallet to sign and send a specific blockchain message.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Never ask users to enter a seed phrase or private key. A normal TON Connect integration does not need either one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the React project
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3a9be7e0x1xn952uqwy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fh3a9be7e0x1xn952uqwy.png" alt="Project setup cheklist" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This tutorial uses React, TypeScript, and Vite.&lt;/p&gt;

&lt;p&gt;Create the project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest ston-wallet-demo &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react-ts
&lt;span class="nb"&gt;cd &lt;/span&gt;ston-wallet-demo
npm &lt;span class="nb"&gt;install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install TON Connect and the STON.fi packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; @tonconnect/ui-react @ston-fi/api @ston-fi/sdk @ton/ton
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Start the development server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The basic wallet connection only requires &lt;code&gt;@tonconnect/ui-react&lt;/code&gt;. The STON.fi packages become necessary when the application starts loading DEX information and building transactions.&lt;/p&gt;

&lt;p&gt;Some browser builds may also require a &lt;code&gt;Buffer&lt;/code&gt; polyfill when serializing a transaction body into a base64 Bag of Cells, or BOC. Add one only when your build reports that &lt;code&gt;Buffer&lt;/code&gt; is unavailable:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; vite-plugin-node-polyfills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then update &lt;code&gt;vite.config.ts&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineConfig&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;nodePolyfills&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;vite-plugin-node-polyfills&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nf"&gt;nodePolyfills&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;buffer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;globals&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;Buffer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;global&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;process&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Publish the TON Connect manifest
&lt;/h2&gt;

&lt;p&gt;Before a wallet connects, it needs to know which application is requesting the connection. TON Connect provides this information through &lt;code&gt;tonconnect-manifest.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Create the following file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public/tonconnect-manifest.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add your application metadata:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-domain.example"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"STON.fi Wallet Demo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iconUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-domain.example/icon-180.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"termsOfUseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-domain.example/terms"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"privacyPolicyUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://your-domain.example/privacy"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Only &lt;code&gt;url&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, and &lt;code&gt;iconUrl&lt;/code&gt; are required. The legal document fields are optional.&lt;/p&gt;

&lt;p&gt;For production, the manifest must be available through a public HTTPS URL. It cannot require authentication or sit behind a browser challenge. The icon should be a publicly accessible PNG or ICO file, with a 180 by 180 pixel PNG being the recommended option. SVG icons are not supported by the documented manifest flow.&lt;/p&gt;

&lt;p&gt;You should be able to open the final URL directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://your-domain.example/tonconnect-manifest.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A desktop extension may sometimes work with a local manifest, but a mobile wallet cannot reliably fetch a file from your computer's &lt;code&gt;localhost&lt;/code&gt;. Use a public preview deployment or an HTTPS development tunnel when testing the QR flow on a phone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mount the TON Connect provider
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;TonConnectUIProvider&lt;/code&gt; makes the TON Connect client available to every component below it.&lt;/p&gt;

&lt;p&gt;Update &lt;code&gt;src/main.tsx&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;TonConnectUIProvider&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./index.css&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;manifestUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_TONCONNECT_MANIFEST_URL&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;
  &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;origin&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/tonconnect-manifest.json`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt; &lt;span class="na"&gt;manifestUrl&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;manifestUrl&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;TonConnectUIProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For production, define the manifest URL explicitly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;VITE_TONCONNECT_MANIFEST_URL=https://your-domain.example/tonconnect-manifest.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using an environment variable makes accidental domain mismatches less likely when the application has development, staging, and production deployments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add the wallet connection interface
&lt;/h2&gt;

&lt;p&gt;TON Connect provides a ready-made button that opens the wallet selection modal and reflects the current connection state.&lt;/p&gt;

&lt;p&gt;Replace &lt;code&gt;src/App.tsx&lt;/code&gt; with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;TonConnectButton&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useIsConnectionRestored&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonWallet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonWallet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;restored&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useIsConnectionRestored&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;restored&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Restoring wallet session...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;STON.fi Wallet Integration&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TonConnectButton&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;header&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Connect a TON wallet to continue.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openModal&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            Open wallet selector
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Connected wallet&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dl&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Address&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Wallet&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Network&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dt&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mainnet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Testnet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dd&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;dl&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;section&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;useTonAddress()&lt;/code&gt; returns an empty string while disconnected and a user-friendly TON address after connection. &lt;code&gt;useTonWallet()&lt;/code&gt; returns the full wallet object, while &lt;code&gt;useIsConnectionRestored()&lt;/code&gt; tells the application whether TON Connect has finished checking for a previously saved session.&lt;/p&gt;

&lt;p&gt;The restoration check is important. Before restoration finishes, a missing wallet does not necessarily mean that the user is disconnected. Redirecting or disabling features too early can create a visible flash of incorrect state.&lt;/p&gt;

&lt;h2&gt;
  
  
  Validate the network before using STON.fi
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwm5kagjpxsl2uil7pj4d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fwm5kagjpxsl2uil7pj4d.png" alt="React Wallet Connection Flow" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;TON mainnet and testnet use different chain identifiers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mainnet: -239
Testnet: -3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The current network is available through:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A mainnet STON.fi integration should block the action when the connected account is not on mainnet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;requireMainnet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Connect a TON mainnet wallet before continuing.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should also include the expected network in every transaction request. The wallet can then reject a transaction when the connected account is on a different network. TON Connect does not provide a conventional runtime network-switch event, so separate deployments are preferable when an application needs both mainnet and testnet experiences.&lt;/p&gt;

&lt;h2&gt;
  
  
  Connect the wallet state to the STON.fi SDK
&lt;/h2&gt;

&lt;p&gt;At this point, the application is connected to a wallet, but it has not interacted with STON.fi.&lt;/p&gt;

&lt;p&gt;A production STON.fi v2 swap should be API-driven:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9zemaplxnlys5yvoxmee.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9zemaplxnlys5yvoxmee.png" alt="From Swap Quote to Wallet Signature" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simulate the requested swap.&lt;/li&gt;
&lt;li&gt;Receive the router metadata from the simulation.&lt;/li&gt;
&lt;li&gt;Create the appropriate router through &lt;code&gt;dexFactory()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Build transaction parameters for the selected swap type.&lt;/li&gt;
&lt;li&gt;Pass those parameters to TON Connect.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This avoids hardcoding a router that may no longer be appropriate for the requested operation. STON.fi's current v2 documentation recommends using the router information returned by the API simulation.&lt;/p&gt;

&lt;p&gt;The following helper prepares a TON-to-jetton transaction:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dexFactory&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/sdk&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StonApiClient&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@ston-fi/api&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Client&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;VITE_TON_RPC_URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;StonApiClient&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;BuildSwapInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildTonToJettonSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;BuildSwapInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;stonApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;simulateSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;offerAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ton&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;slippageTolerance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;0.01&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routerInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contracts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;dexFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tonClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proxyTon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;contracts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pTON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;routerInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ptonMasterAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getSwapTonToJettonTxParams&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;userWalletAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;offerAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;minAskAmount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;minAskUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;simulation&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;askAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;proxyTon&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;offerUnits&lt;/code&gt; must use blockchain units, not a human-readable decimal string. Token precision is not universal. Some TON assets use nine decimal places, while others use a different value, so retrieve the asset metadata and convert the entered amount according to that asset's decimals. Do not apply nine decimals to every token.&lt;/p&gt;

&lt;p&gt;The simulation also provides &lt;code&gt;minAskUnits&lt;/code&gt;. Reusing it in the transaction ensures that the signed operation reflects the minimum output calculated for the selected slippage tolerance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Send the STON.fi transaction through TON Connect
&lt;/h2&gt;

&lt;p&gt;The STON.fi SDK returns transaction parameters containing the destination contract, attached value, and serialized message body.&lt;/p&gt;

&lt;p&gt;Convert them into the shape expected by TON Connect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;StonTransactionParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;toTonConnectRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;StonTransactionParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;validUntil&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;network&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;address&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
        &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;toBoc&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;base64&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can now use it inside a React component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;useTonWallet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@tonconnect/ui-react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;buildTonToJettonSwap&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./stonSwap&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;SwapButtonProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SwapButton&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;SwapButtonProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonWallet&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;walletAddress&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonAddress&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTonConnectUI&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPending&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleSwap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openModal&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;wallet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chain&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;-239&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A TON mainnet wallet is required.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setPending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;txParams&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;buildTonToJettonSwap&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="nx"&gt;walletAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;askJettonAddress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;offerUnits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;

      &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;tonConnectUI&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendTransaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;toTonConnectRequest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;txParams&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;unknownError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nx"&gt;unknownError&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;
          &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;unknownError&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;
          &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;The transaction could not be prepared or sent.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setPending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSwap&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pending&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Preparing transaction...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Review swap in wallet&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"alert"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling &lt;code&gt;sendTransaction()&lt;/code&gt; does not silently execute the swap. It opens the wallet approval flow. The wallet owner can inspect and reject the request before it is broadcast. STON.fi documents the same boundary: the SDK generates &lt;code&gt;txParams&lt;/code&gt;, and TON Connect sends the resulting message to the wallet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Production checks and common failures
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rhxu8z15j0r33iji8ic.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F6rhxu8z15j0r33iji8ic.png" alt="Mainnet Checks and Common Errors" width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before enabling real swaps, add a review screen that displays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The input asset and amount.&lt;/li&gt;
&lt;li&gt;The output asset.&lt;/li&gt;
&lt;li&gt;The expected output.&lt;/li&gt;
&lt;li&gt;The minimum output.&lt;/li&gt;
&lt;li&gt;The selected slippage tolerance.&lt;/li&gt;
&lt;li&gt;The connected address and network.&lt;/li&gt;
&lt;li&gt;Any estimated network or protocol costs available to the interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not prepare a quote once and reuse it indefinitely. Market conditions and pool reserves can change. Request a fresh simulation shortly before building the transaction.&lt;/p&gt;

&lt;p&gt;Common integration problems include:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Problem&lt;/th&gt;
&lt;th&gt;Likely cause&lt;/th&gt;
&lt;th&gt;What to check&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Wallet modal opens but connection fails&lt;/td&gt;
&lt;td&gt;Manifest unavailable&lt;/td&gt;
&lt;td&gt;Public HTTPS URL, valid JSON, icon URL, and unrestricted access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mobile wallet cannot load the app identity&lt;/td&gt;
&lt;td&gt;Manifest points to localhost&lt;/td&gt;
&lt;td&gt;Deploy the manifest or use a public HTTPS development URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;UI briefly says disconnected&lt;/td&gt;
&lt;td&gt;Session restoration is unfinished&lt;/td&gt;
&lt;td&gt;Wait for &lt;code&gt;useIsConnectionRestored()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wallet rejects the transaction network&lt;/td&gt;
&lt;td&gt;Mainnet and testnet mismatch&lt;/td&gt;
&lt;td&gt;Check &lt;code&gt;wallet.account.chain&lt;/code&gt; and set &lt;code&gt;network: "-239"&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser reports &lt;code&gt;Buffer is not defined&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;BOC serialization lacks a polyfill&lt;/td&gt;
&lt;td&gt;Add a targeted Buffer polyfill&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Quote works but transaction fails&lt;/td&gt;
&lt;td&gt;Quote is stale, balance changed, or TON for fees is insufficient&lt;/td&gt;
&lt;td&gt;Simulate again and recheck balances&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Swap uses an unexpected router&lt;/td&gt;
&lt;td&gt;Contract address was hardcoded&lt;/td&gt;
&lt;td&gt;Use the router returned by the latest STON.fi simulation&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;STON.fi's REST API currently serves the documented production workflow from mainnet. The v2 testnet path requires manually configured contracts and liquidity, so it should not be treated as a full mirror of the mainnet API-driven experience.&lt;/p&gt;

&lt;p&gt;A practical final test is to connect a separate wallet with a small balance, simulate a modest transaction, review every wallet field, and confirm the resulting operation on-chain before expanding the integration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Frequently Asked Questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Can I connect a wallet directly to the official STON.fi application?
&lt;/h3&gt;

&lt;p&gt;Yes. Open the official STON.fi application, select &lt;strong&gt;Connect Wallet&lt;/strong&gt;, choose a compatible TON wallet, and approve the connection. The developer steps in this tutorial are for applications that want to integrate TON Connect and STON.fi functionality into their own interface.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does connecting a wallet give STON.fi access to the private key?
&lt;/h3&gt;

&lt;p&gt;No. TON Connect establishes a communication session with the wallet, but the private key remains inside the wallet application. A dApp can request a transaction, but the wallet owner must review and approve that request separately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Which TON Connect package should a React application use?
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;@tonconnect/ui-react&lt;/code&gt; for React and Next.js applications. It provides the provider, connection button, modal, and React hooks. Non-React browser applications can use &lt;code&gt;@tonconnect/ui&lt;/code&gt;, while headless or highly customized integrations can use &lt;code&gt;@tonconnect/sdk&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does the TON Connect manifest need a public HTTPS URL?
&lt;/h3&gt;

&lt;p&gt;The wallet fetches the manifest independently to identify the requesting application. A local file, protected endpoint, authentication wall, or browser challenge can prevent the wallet from reading it. HTTPS also gives the wallet a stable origin for displaying the application identity.&lt;/p&gt;

&lt;h3&gt;
  
  
  How can the application tell whether a wallet uses mainnet?
&lt;/h3&gt;

&lt;p&gt;Read &lt;code&gt;wallet.account.chain&lt;/code&gt;. TON mainnet uses &lt;code&gt;"-239"&lt;/code&gt; and testnet uses &lt;code&gt;"-3"&lt;/code&gt;. For a mainnet STON.fi application, validate the value after connection and include &lt;code&gt;network: "-239"&lt;/code&gt; in transaction requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Is connecting a wallet the same as authenticating a user?
&lt;/h3&gt;

&lt;p&gt;Not necessarily. A public wallet address can identify a connected account, but an application that needs secure backend authentication should request and verify &lt;code&gt;ton_proof&lt;/code&gt;. A connection alone should not be treated as proof that an HTTP request came from the wallet owner.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can STON.fi v2 swaps be fully tested through the public API on testnet?
&lt;/h3&gt;

&lt;p&gt;Not through the same production API-driven path. STON.fi documents its REST API as mainnet-focused. Testnet swaps require manually selected contracts, test assets, and funded liquidity pools. Use that environment for controlled development rather than assuming it matches mainnet liquidity or routing.&lt;/p&gt;

&lt;h3&gt;
  
  
  What should be checked before requesting a STON.fi swap signature?
&lt;/h3&gt;

&lt;p&gt;Check the connected network, wallet balance, asset addresses, token decimals, expected output, minimum received, slippage tolerance, transaction destination, and attached TON value. Build the transaction from a fresh STON.fi simulation and let the wallet display the final approval request.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
