> For the complete documentation index, see [llms.txt](https://docs.ston.fi/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ston.fi/developer-section/omniston/sdk/react.md).

# React

Follow the Omniston SDK workflow from RFQ and quote acceptance to wallet signing and trade tracking.

Use `@ston-fi/omniston-sdk-react` in React applications. It provides a provider and hooks on top of the [Omniston SDK](/developer-section/omniston/sdk/nodejs.md), a typed wrapper over the [Omniston WebSocket API](/developer-section/omniston/swap/overview.md). With hooks, you make individual requests and receive quote updates and settlement updates.

This guide uses Omniston API v1beta8 and Omniston SDK 0.8.x. The examples show the primary integration steps. Your application controls when to accept a quote. It must also supply wallet signing, transaction submission, and persistence.

The Omniston SDK builds unsigned transactions or order payloads. The wallet signs them.

## Installation

Install the [Omniston React SDK package](https://www.npmjs.com/package/@ston-fi/omniston-sdk-react):

```sh
npm install @ston-fi/omniston-sdk-react
```

## Configuration

### API URL

Select an [environment](/developer-section/omniston/environments.md). Set `apiUrl` to its Trading / RFQ WebSocket URL when you create the `Omniston` client. Use the same client for requests and subscriptions in your application.

```tsx
import { Omniston, OmnistonProvider } from "@ston-fi/omniston-sdk-react";
import type { PropsWithChildren } from "react";

const apiUrl = "wss://omni-ws.ston.fi";
const omniston = new Omniston({ apiUrl });

export function AppProviders({ children }: PropsWithChildren) {
  return <OmnistonProvider omniston={omniston}>{children}</OmnistonProvider>;
}
```

### Query client

The React SDK hooks use TanStack Query. Without a `queryClient` prop, `OmnistonProvider` creates its own `QueryClient` and wraps its children in a `QueryClientProvider`.

To share an existing client, pass it explicitly as `queryClient`. In this case, `OmnistonProvider` creates neither a client nor a `QueryClientProvider`. Wrap it in your application's `QueryClientProvider` using the same client:

```tsx
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

const queryClient = new QueryClient();

export function AppProviders({ children }: PropsWithChildren) {
  return (
    <QueryClientProvider client={queryClient}>
      <OmnistonProvider omniston={omniston} queryClient={queryClient}>
        {children}
      </OmnistonProvider>
    </QueryClientProvider>
  );
}
```

### Transport

**Connection**

The Omniston SDK automatically opens the WebSocket connection for the first Omniston API request. This applies to individual requests and streaming subscriptions. For streaming hooks, the SDK sends the request when the hook subscribes to the stream.

**Default transport**

By default, `Omniston` uses `AutoReconnectTransport` around `WebSocketTransport`. After a connection error, it makes a maximum of five reconnection attempts. The first attempt starts after one second. The delay doubles for each subsequent attempt.

The Omniston SDK keeps local stream subscriptions open during reconnection. After reconnection, it opens their server subscriptions again. An RFQ can receive a new `ack` with a new RFQ ID after reconnection. When the server sends `unsubscribed`, the stream ends. The SDK does not automatically open that stream again.

**Custom transport**

Pass `transport` to the `Omniston` constructor to replace the default transport. Select an implementation that meets your application's reconnection requirements:

* Configure `AutoReconnectTransport` around `WebSocketTransport` to use a different automatic retry policy.
* Use `new WebSocketTransport(apiUrl)` to let your application control reconnection.
* Implement the exported `Transport` interface for your own transport. Your transport must have the `messages` and `connectionStatusEvents` observables. It must also have the `connect()`, `reconnect()`, `send()`, and `close()` methods. The transport must send and receive the JSON-RPC messages for the Omniston WebSocket API. It must report connection status changes to let the Omniston SDK restore subscriptions.

For example, configure the automatic retry policy as follows:

```ts
import {
  AutoReconnectTransport,
  Omniston,
  WebSocketTransport,
} from "@ston-fi/omniston-sdk-react";

const omniston = new Omniston({
  apiUrl,
  transport: new AutoReconnectTransport({
    transport: new WebSocketTransport(apiUrl),
    maxRetries: 10,
    reconnectDelayMs: 500,
  }),
});
```

**Connection status**

Use `useConnectionStatus()` to read the current status and receive status changes.

```tsx
import { useConnectionStatus } from "@ston-fi/omniston-sdk-react";

function ConnectionStatus() {
  const connectionStatus = useConnectionStatus();

  return <div>Connection: {connectionStatus}</div>;
}
```

### Logging

The Omniston SDK does not write logs by default. For connection and Omniston API diagnostics, pass a compatible logger, such as `console`:

```ts
const omniston = new Omniston({ apiUrl, logger: console });
```

## Request for quote

An RFQ (request for quote) contains the assets, amount, and settlement methods that your application supports. Omniston returns a stream of quotes. A quote request does not submit a trade. For an overview of the Omniston protocol, see [How Omniston works](/developer-section/omniston/how-omniston-works.md).

Use an `AssetId` for each asset. Write the amount as a decimal string of integer base units. `inputUnits` sets the amount that the trader spends. `outputUnits` sets the net output amount after fees. See [Supported chains and assets](/developer-section/omniston/chains.md) and [Amounts and fee fields](/developer-section/omniston/swap/v1beta8.md#amounts-and-fee-fields).

### Settlement methods

A settlement method controls how the protocol executes a trade after the trader accepts a quote. The Omniston protocol supports two settlement methods:

* `swap` — available only for intrachain swaps on TON. It executes the trade through swap routes. It does not create a persistent order.
* `order` — supports cross-chain swaps with HTLC settlement. Resolvers fill escrow-backed or signed orders. This method also supports intrachain orders on TON.

Set the methods that your application supports in `settlementParams`. For TON intrachain swaps, you can enable the two methods. Use the method from `quote.settlementData.$case`. For cross-chain swaps, use `order`. To compare the methods, see [Settlement modes in How Omniston works](/developer-section/omniston/how-omniston-works.md#settlement-modes).

### Settlement params

The two settlement methods support optional integrator-fee settings through top-level `QuoteRequest` fields:

* `integratorAddress` — the address on the destination blockchain where the integrator receives fees.
* `integratorFeePips` — the requested fee rate in pips, where one pip is 0.0001%.

The protocol charges the fee in the output asset. See [Integrator fees](/developer-section/omniston/referral-fees.md) for fee configuration and collection mechanisms. Set method-specific options in `settlementParams`. The following examples show these options.

### Swap quote request

This RFQ exchanges 1 TON for USDT on TON. It uses swap settlement only.

```ts
import type { QuoteRequest } from "@ston-fi/omniston-sdk-react";

const quoteRequest: QuoteRequest = {
  inputAsset: { // Native TON
    chain: {
      $case: "ton",
      value: { kind: { $case: "native", value: {} } },
    },
  },
  outputAsset: { // USDT on TON
    chain: {
      $case: "ton",
      value: {
        kind: {
          $case: "jetton",
          value: "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
        },
      },
    },
  },
  amount: { $case: "inputUnits", value: "1000000000" }, // 1 TON (9 decimals)
  settlementParams: [
    {
      params: {
        $case: "swap",
        value: {
          maxPriceSlippagePips: 10_000, // 1%
          flexibleIntegratorFee: true,
        },
      },
    },
  ],
};
```

`maxPriceSlippagePips` uses millionths: `10_000` is 1%. The `flexibleIntegratorFee` option applies only to swap settlement. With this option, the effective integrator fee can be lower if necessary to meet the route's fee constraints.

### Order quote request

This RFQ exchanges 1 USDT on TON for USDC on Base. It uses order settlement only. When you build the order, supply a Base destination address.

```ts
import type { QuoteRequest } from "@ston-fi/omniston-sdk-react";

const quoteRequest: QuoteRequest = {
  inputAsset: { // USDT on TON
    chain: {
      $case: "ton",
      value: {
        kind: {
          $case: "jetton",
          value: "EQCxE6mUtQJKFnGfaROTKOt1lZbDiiX1kCixRv7Nw2Id_sDs",
        },
      },
    },
  },
  outputAsset: { // USDC on Base
    chain: {
      $case: "base",
      value: {
        kind: {
          $case: "erc20",
          value: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
        },
      },
    },
  },
  amount: { $case: "inputUnits", value: "1000000" }, // 1 USDT (6 decimals)
  settlementParams: [
    {
      params: {
        $case: "order",
        value: {},
      },
    },
  ],
};
```

Quotes are available only for supported chain pairs with available liquidity.

### Send an RFQ

Pass the `quoteRequest` object from one of the two examples to `useRfq()` to get the RFQ stream. The hook subscribes to this stream and sends the quote request to the Omniston API.

```tsx
import { useRfq } from "@ston-fi/omniston-sdk-react";

function QuoteStream() {
  const { data: rfqEvent, error } = useRfq(quoteRequest);

  // Handle rfqEvent and error as shown in the next section.
  return null;
}
```

## Handle quote updates

`useRfq()` returns the latest quote update event in `data`. Subscription failures are available in `error`.

Keep the latest quote available for the trader to accept. When no valid quote is available, clear the previous quote. If the subscription closes, clear the previous quote.

```tsx
import { useRfq, type Quote } from "@ston-fi/omniston-sdk-react";

function QuoteStream({ onAccept }: { onAccept: (quote: Quote) => void }) {
  const { data: rfqEvent, error } = useRfq(quoteRequest);

  if (error) {
    return <div>RFQ stream failed: {String(error)}</div>;
  }

  switch (rfqEvent?.$case) {
    case "ack":
      return <div>RFQ id: {rfqEvent.value.rfqId}</div>;
    case "quoteUpdated":
      return (
        <button onClick={() => onAccept(rfqEvent.value)}>
          Accept quote: {rfqEvent.value.quoteId} ({rfqEvent.value.outputUnits})
        </button>
      );
    case "noQuote":
      return <div>No quote for RFQ: {rfqEvent.rfqId}</div>;
    case "unsubscribed":
      return <div>Quote stream closed by server</div>;
    default:
      return <div>Waiting for quote...</div>;
  }
}
```

### Quote update events

| Event          | Meaning                                                                            | Application action                                                        |
| -------------- | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |
| `ack`          | The server accepted the RFQ and gave it `value.rfqId`.                             | Record the RFQ ID. Wait for a quote.                                      |
| `quoteUpdated` | `value` contains the current `Quote`, including its `quoteId` and settlement data. | Replace the previous quote.                                               |
| `noQuote`      | There is currently no valid quote for this RFQ.                                    | Clear the previous quote. Continue to receive updates.                    |
| `unsubscribed` | The server closed this subscription.                                               | Do not use the stream again. If necessary, create a new RFQ subscription. |

The Omniston SDK filters out `keepAlive` messages from the Omniston API. It adds `rfqId` to `quoteUpdated` and `noQuote` events. Subscription failures are available in the hook's `error` field.

Each new quote replaces the previous quote. This can occur because the terms changed or the previous quote expired. Accept only the current valid quote. For order quotes, check `tradeStartDeadline` in the settlement data. See [Lifecycle and timing](/developer-section/omniston/how-omniston-works.md#lifecycle-and-timing).

## Start a trade

### Accept a quote

When the trader accepts a valid quote from a `quoteUpdated` event, more RFQ updates are not necessary. You can stop the RFQ subscription by unmounting its last consumer. Keep the accepted quote in the parent component:

```tsx
import { useState } from "react";
import type { Quote } from "@ston-fi/omniston-sdk-react";

function QuoteSelection() {
  const [acceptedQuote, setAcceptedQuote] = useState<Quote>();

  if (acceptedQuote) {
    // Use this quote in the applicable build-and-sign flow below.
    return <div>Accepted quote: {acceptedQuote.quoteId}</div>;
  }

  return <QuoteStream onAccept={setAcceptedQuote} />;
}
```

Use the accepted quote to build the transaction or order. Then, sign the transaction or order with the wallet.

In the following examples, `quote` is the accepted `Quote` from a `quoteUpdated` event. Use the branch for its settlement method and source chain. Replace the example wallet addresses with your wallet addresses on the applicable networks.

### Build and sign swap transaction

For the selected swap quote, use `useTonBuildSwap()` to build an unsigned swap transaction:

```tsx
import { useTonBuildSwap, type ChainAddress, type QuoteOfType } from "@ston-fi/omniston-sdk-react";

const traderAddress: ChainAddress = {
  chain: { $case: "ton", value: "EQ..." },
};

function useSwapTransaction(quote: QuoteOfType<"swap">) {
  const { data: swapTx, error } = useTonBuildSwap({
    quoteId: quote.quoteId,
    transferSrcAddress: traderAddress,
  });

  return { swapTx, error };
}
```

Once `swapTx` is available, sign all `swapTx.messages` with your wallet. Send all messages with your selected [TON transaction-sending method](/developer-section/common/transaction-sending.md). See [TON wallet integration](/developer-section/omniston/sdk/ton.md) to adapt the Omniston SDK transaction to your wallet.

For `outgoingTxQuery`, get the outgoing transaction hash or another supported identifier. Use this identifier to track the swap with `useSwapTrack()`. See [Submit and identify a swap](/developer-section/omniston/sdk/ton.md#submit-and-identify-a-swap).

### Build and sign order transaction

Select the build and submission flow for the order's source blockchain:

| Source blockchain | Build                         | Sign and submit                                                                        |
| ----------------- | ----------------------------- | -------------------------------------------------------------------------------------- |
| [TON](#ton)       | `useTonBuildEscrowTransfer()` | Sign the returned transaction messages with a TON wallet. Send the messages.           |
| [EVM](#evm)       | `useEvmBuildOrderPayload()`   | Sign the returned order payload. Call `orderRegisterSignedOrder()`.                    |
| [TRON](#tron)     | `useEvmBuildOrderPayload()`   | Sign the returned order payload with a TRON wallet. Call `orderRegisterSignedOrder()`. |

The cross-chain order examples use `secretHashes`. Your application supplies this `Uint8Array[]` of HTLC secret hashes. See [HTLC secrets](#htlc-secrets) for the relation between these hashes, the original secrets, and order tracking.

#### TON

TON supports bilateral orders within TON and HTLC orders across blockchains. The two order types use `useTonBuildEscrowTransfer()`. Use the example for the selected order quote.

**Bilateral order**

A bilateral order is a TON → TON order that does not use HTLC secrets. For the selected bilateral order quote, build the escrow transfer as follows:

```tsx
import {
  useTonBuildEscrowTransfer,
  type ChainAddress,
  type QuoteOfType,
} from "@ston-fi/omniston-sdk-react";

const traderAddress: ChainAddress = {
  chain: { $case: "ton", value: "EQ..." },
};

function useOrderTransaction(quote: QuoteOfType<"order">) {
  const { data: orderTx, error } = useTonBuildEscrowTransfer({
    quoteId: quote.quoteId,
    ownerSrcAddress: traderAddress,
    traderDstAddress: traderAddress,
  });

  return { orderTx, error };
}
```

Track this bilateral order with `useOrderTrack()`. HTLC secret disclosure does not apply.

**HTLC order**

An HTLC order from TON to another blockchain uses HTLC secrets. See [HTLC secrets](#htlc-secrets) for an explanation of `secretHashes`. For the selected HTLC order quote, build the escrow transfer as follows:

```tsx
import {
  useTonBuildEscrowTransfer,
  type ChainAddress,
  type QuoteOfType,
} from "@ston-fi/omniston-sdk-react";

const traderAddress: ChainAddress = {
  chain: { $case: "ton", value: "EQ..." },
};

const destinationAddress: ChainAddress = {
  chain: { $case: "base", value: "0x..." },
};

function useOrderTransaction(quote: QuoteOfType<"order">) {
  const { data: orderTx, error } = useTonBuildEscrowTransfer({
    quoteId: quote.quoteId,
    ownerSrcAddress: traderAddress,
    traderDstAddress: destinationAddress,
    htlcSecrets: {
      secretMode: {
        $case: "provided",
        value: { hashes: secretHashes },
      },
    },
  });

  return { orderTx, error };
}
```

Once `orderTx` is available, sign `orderTx.messages` with your TON wallet. Send the messages as shown in [TON wallet integration](/developer-section/omniston/sdk/ton.md). Order tracking uses the source owner address and `quoteId`. The `outgoingTxQuery` identifier is not necessary.

#### EVM

For an order with an EVM source, use this procedure:

1. Build the order payload with `useEvmBuildOrderPayload()`.
2. Sign the payload with the source owner wallet.
3. Register the signed order with `orderRegisterSignedOrder()`.

In this example, `signEvmOrder()` is your application's function for EIP-712 signing and `SignedOrder` construction. See [EVM signature shapes](/developer-section/omniston/sdk/evm/evm-signature.md) for the signature requirements of different wallet kinds.

See [HTLC secrets](#htlc-secrets) for an explanation of `secretHashes`.

```tsx
import {
  useEvmBuildOrderPayload,
  useOmniston,
  type ChainAddress,
  type QuoteOfType,
} from "@ston-fi/omniston-sdk-react";

const traderAddress: ChainAddress = {
  chain: { $case: "base", value: "0x..." },
};
const destinationAddress: ChainAddress = {
  chain: { $case: "ton", value: "EQ..." },
};

function EvmOrderBuild({ quote }: { quote: QuoteOfType<"order"> }) {
  const omniston = useOmniston();

  const { data: orderPayload, error } = useEvmBuildOrderPayload({
    quoteId: quote.quoteId,
    ownerSrcAddress: traderAddress,
    traderDstAddress: destinationAddress,
    htlcSecrets: {
      secretMode: {
        $case: "provided",
        value: { hashes: secretHashes },
      },
    },
  });

  async function registerSignedOrder() {
    if (!orderPayload) return;

    const signedOrder = await signEvmOrder(orderPayload);

    await omniston.orderRegisterSignedOrder({
      quoteId: quote.quoteId,
      ownerSrcAddress: traderAddress,
      signedOrder,
      serializedOrderDetails: orderPayload.serializedOrderDetails,
    });
  }

  if (error) {
    return <div>Order payload failed: {String(error)}</div>;
  }

  return (
    <button disabled={!orderPayload} onClick={registerSignedOrder}>
      Sign and register order
    </button>
  );
}
```

Before registration, use one of these methods:

* Make sure that you have the necessary confirmed token allowance.
* Supply the supported permit fields when you build the payload.

Include `orderExtension` in the signed order. Pass `serializedOrderDetails` back without changes. See [EVM wallet integration](/developer-section/omniston/sdk/evm.md) for wallet kinds, allowance, and signature encoding.

#### TRON

For an order with a TRON source, use this procedure:

1. Build the order payload with `useEvmBuildOrderPayload()`.
2. Sign the payload with the source owner wallet.
3. Register the signed order with `orderRegisterSignedOrder()`.

In this example, `signTronOrder()` is your application's function for TRON wallet signing and `SignedOrder` construction. See [TRON wallet integration](/developer-section/omniston/sdk/tron.md) for the TRON-specific signing flow and reference implementation.

See [HTLC secrets](#htlc-secrets) for an explanation of `secretHashes`.

```tsx
import {
  useEvmBuildOrderPayload,
  useOmniston,
  type ChainAddress,
  type QuoteOfType,
} from "@ston-fi/omniston-sdk-react";

const traderAddress: ChainAddress = {
  chain: { $case: "tron", value: "T..." },
};
const destinationAddress: ChainAddress = {
  chain: { $case: "ton", value: "EQ..." },
};

function TronOrderBuild({ quote }: { quote: QuoteOfType<"order"> }) {
  const omniston = useOmniston();

  const { data: orderPayload, error } = useEvmBuildOrderPayload({
    quoteId: quote.quoteId,
    ownerSrcAddress: traderAddress,
    traderDstAddress: destinationAddress,
    htlcSecrets: {
      secretMode: {
        $case: "provided",
        value: { hashes: secretHashes },
      },
    },
  });

  async function registerSignedOrder() {
    if (!orderPayload) return;

    const signedOrder = await signTronOrder(orderPayload);

    await omniston.orderRegisterSignedOrder({
      quoteId: quote.quoteId,
      ownerSrcAddress: traderAddress,
      signedOrder,
      serializedOrderDetails: orderPayload.serializedOrderDetails,
    });
  }

  if (error) {
    return <div>Order payload failed: {String(error)}</div>;
  }

  return (
    <button disabled={!orderPayload} onClick={registerSignedOrder}>
      Sign and register order
    </button>
  );
}
```

Before registration, make sure that you have a confirmed TRC-20 token allowance for the source-side protocol contract. Include `orderExtension` in the signed order. Pass `serializedOrderDetails` back without changes.

#### HTLC secrets

The number of secret hashes in an HTLC order sets the maximum number of executions. Each execution uses one hash. Omniston currently supports only one execution per HTLC order. Thus, `secretHashes` must contain one hash.

For trader-provided HTLC secrets, the data flow is:

1. Put the 32-byte secret hash in `secretHashes`. Use the quote's `htlcHashingFunction` to calculate the hash.
2. When you build the transaction or order payload, pass these hashes in `htlcSecrets.secretMode` with `$case: "provided"`.
3. Keep the original secrets with the accepted `quoteId` and their execution indices. The order contains the hashes. Keep the original secrets private until disclosure.
4. During `useOrderTrack()`, check the input position phase and output position phase for each execution. When the two positions meet the disclosure conditions, disclose that execution's original secret with `orderDiscloseHtlcSecret()`. See [HTLC secret disclosure](#htlc-secret-disclosure) for the necessary phases.

## Track trade status

After transaction broadcast or signed order registration, select the tracking method for the accepted quote's settlement method:

* For `swap`, use `useSwapTrack()`.
* For `order`, use `useOrderTrack()`.

The two methods give updates on the trade's progress and result.

### Track swap status

Pass these values to `useSwapTrack()`:

* The `quoteId` of the accepted swap `quote`.
* The trader address that you passed to `useTonBuildSwap()`.
* The `outgoingTxQuery` identifier from the swap transaction submission.

```tsx
import { useSwapTrack, type ChainAddress, type QuoteOfType } from "@ston-fi/omniston-sdk-react";

function SwapTracking({
  quote,
  traderAddress,
  outgoingTxQuery,
}: {
  quote: QuoteOfType<"swap">;
  traderAddress: ChainAddress;
  outgoingTxQuery: string;
}) {
  const { data: swapEvent, error } = useSwapTrack({
    quoteId: quote.quoteId,
    traderAddress,
    outgoingTxQuery,
  });

  if (error) {
    return <div>Swap tracking failed: {String(error)}</div>;
  }

  switch (swapEvent?.$case) {
    case "awaitingTransfer":
      return <div>Waiting for the source transfer</div>;
    case "progress":
      return (
        <div>
          Swap status: {swapEvent.value.status}
          <pre>{JSON.stringify(swapEvent.value.routes, null, 2)}</pre>
        </div>
      );
    case "unsubscribed":
      return <div>Swap tracking closed by server</div>;
    default:
      return <div>Waiting for swap updates...</div>;
  }
}
```

`progress` includes the aggregate trade status and route, step, and chunk results.

### Track order status

Use the source-side `traderAddress` that you passed as `ownerSrcAddress` in the selected order branch. TON-funded orders and signed orders from EVM or TRON use `useOrderTrack()`:

```tsx
import { useOrderTrack, type ChainAddress, type Order, type QuoteOfType } from "@ston-fi/omniston-sdk-react";
import { useState } from "react";

function OrderTracking({
  quote,
  traderAddress,
}: {
  quote: QuoteOfType<"order">;
  traderAddress: ChainAddress;
}) {
  const { data: orderEvent, error } = useOrderTrack({
    quoteId: quote.quoteId,
    traderAddress,
  });
  const [order, setOrder] = useState<Order>();

  if (orderEvent?.$case === "order" && orderEvent.value !== order) {
    setOrder(orderEvent.value);
  }

  if (error) {
    return <div>Order tracking failed: {String(error)}</div>;
  }

  if (order) {
    // For HTLC orders, check execution phases before disclosing the secret.
    return (
      <div>
        Order status: {order.status}
        <pre>{JSON.stringify(order.executions, null, 2)}</pre>
      </div>
    );
  }

  switch (orderEvent?.$case) {
    case "unsubscribed":
      return <div>Order tracking closed by server</div>;
    default:
      return <div>Waiting for order updates...</div>;
  }
}
```

Keep the last `order` snapshot after `unsubscribed`; closing the stream does not change the trade result.

The primary outcomes in `Order.status` are:

* `TRADE_STATUS_FULLY_FILLED`
* `TRADE_STATUS_PARTIALLY_FILLED`
* `TRADE_STATUS_CANCELLED`
* `TRADE_STATUS_FAILED`

See [Reading completion in order settlement](/developer-section/omniston/how-omniston-works.md#reading-completion-in-order-settlement).

### HTLC secret disclosure

For HTLC orders, examine the executions in each `order` update from `useOrderTrack()`. Before disclosure, check the execution's input position phase and output position phase. The two phases must meet the conditions in [When to call `orderDiscloseHtlcSecret()`](/developer-section/omniston/how-omniston-works.md#when-to-call-orderdisclosehtlcsecret).

For each `execution` that meets the two conditions, use its `index` as `executionIndex`. Use the original `secret` whose hash you supplied for that execution when you built the order. Pass these values to `useDiscloseHtlcSecret()`. Keep the query disabled and trigger disclosure only after checking the phases:

```tsx
import { useDiscloseHtlcSecret, type DiscloseHtlcSecretRequest } from "@ston-fi/omniston-sdk-react";

function DiscloseSecret({ quoteId, executionIndex, secret }: DiscloseHtlcSecretRequest) {
  const { refetch: disclose, error } = useDiscloseHtlcSecret(
    { quoteId, executionIndex, secret },
    { enabled: false },
  );

  return (
    <div>
      <button onClick={() => void disclose()}>Disclose secret</button>
      {error ? <div>Secret disclosure failed: {String(error)}</div> : null}
    </div>
  );
}
```

Continue to receive `useOrderTrack()` updates to monitor the trade result. The disclosure response acknowledges the secret. It does not show that the trade is completed.

## Active orders and recovery

`useActiveOrders()` returns a snapshot of active orders for a source-side trader address. Use it after an application reload or to update an active-order list. For periodic updates, set `refetchInterval` in the hook's query options.

```tsx
import { useActiveOrders, type ChainAddress } from "@ston-fi/omniston-sdk-react";

function ActiveOrdersList({ traderAddress }: { traderAddress: ChainAddress }) {
  const { data, error } = useActiveOrders({ traderAddress });

  if (error) {
    return <div>Active orders failed: {String(error)}</div>;
  }

  return (
    <ul>
      {data?.activeOrders.map((activeOrder) => (
        <li key={activeOrder.quote.quoteId}>
          Quote: {activeOrder.quote.quoteId}, status: {activeOrder.order.status}
          {/* Resume useOrderTrack() for orders your application needs to monitor. */}
        </li>
      ))}
    </ul>
  );
}
```

Restore the secrets for trader-managed HTLC orders from your own storage. This snapshot does not recover secret preimages.

## Cleanup

When pricing or tracking updates are no longer necessary, unmount the components that consume the applicable stream. The SDK unsubscribes when the query loses its last observer, including when the last consumer unmounts or changes its request parameters.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.ston.fi/developer-section/omniston/sdk/react.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
