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

# pollStatus

> Polls Li.Fi for the status of a transfer until it reaches a terminal state.

**Function Signature**

Four callable forms. The first is the protocol requirement, which takes all three arguments; the other three are convenience overloads on `LifiProtocol` that supply defaults.

```swift theme={null}
// All three arguments
public func pollStatus(
    request: LifiStatusRequest,
    onUpdate: ((LifiStatusRawResponse) -> Bool)?,
    options: LifiPollStatusOptions
) async throws -> LifiStatusRawResponse

// Default options, no callback
public func pollStatus(request: LifiStatusRequest) async throws -> LifiStatusRawResponse

// Custom options, no callback
public func pollStatus(request: LifiStatusRequest, options: LifiPollStatusOptions) async throws -> LifiStatusRawResponse

// Callback, default options
public func pollStatus(
    request: LifiStatusRequest,
    onUpdate: @escaping (LifiStatusRawResponse) -> Bool
) async throws -> LifiStatusRawResponse
```

**Description**

Polls the Li.Fi status endpoint until the transfer reaches a terminal state, then returns the final status. This is the same polling `tradeAsset` performs internally after each step confirms, exposed for manual flows where you already hold a transaction hash.

Returning `false` from `onUpdate` stops polling early and returns the last status received — it is not an error. Returning `true` continues polling.

`onUpdate` only fires on non-terminal polls. A `DONE` status returns immediately and a `FAILED` status throws, so neither reaches the callback — read the terminal state from the return value rather than from `onUpdate`.

**Parameters**

The Required column describes the three-argument protocol requirement, where neither `onUpdate` nor `options` carries a default. The convenience overloads supply both, which is why most call sites pass only `request`.

| Parameter  | Type                                 | Required                                                    | Description                                                                                                                              |
| ---------- | ------------------------------------ | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `request`  | `LifiStatusRequest`                  | Yes                                                         | Identifies the transfer — `txHash`, `fromChain`, `toChain`, and an optional `bridge`.                                                    |
| `onUpdate` | `((LifiStatusRawResponse) -> Bool)?` | Yes on the protocol requirement; defaulted by the overloads | Called on each non-terminal poll with the latest status. Return `false` to stop early. Pass `nil` on the three-argument form to skip it. |
| `options`  | `LifiPollStatusOptions`              | Yes on the protocol requirement; defaulted by the overloads | Polling cadence and timeout.                                                                                                             |

`LifiPollStatusOptions`:

| Option           | Type  | Default  | Description                                                                                              |
| ---------------- | ----- | -------- | -------------------------------------------------------------------------------------------------------- |
| `everyMs`        | `Int` | `10000`  | Interval between polls, in milliseconds. Values below `100` are raised to `100` to prevent busy-waiting. |
| `initialDelayMs` | `Int` | `0`      | Delay before the first poll, in milliseconds.                                                            |
| `timeoutMs`      | `Int` | `600000` | Overall polling timeout, in milliseconds.                                                                |

**Returns**

**`LifiStatusRawResponse`** — the final status payload from Li.Fi, or the last one received if `onUpdate` returned `false`.

**Throws**

| Case                                             | When                                      |
| ------------------------------------------------ | ----------------------------------------- |
| `LifiTradeAssetError.pollTimeout`                | Polling exceeded `timeoutMs`.             |
| `LifiTradeAssetError.lifiTransferFailed(String)` | Li.Fi reported a `FAILED` terminal state. |

Also throws `CancellationError` if the surrounding `Task` is cancelled.

**Example Usage**

```swift theme={null}
import PortalSwift

do {
    let txHash = "0xYOUR_TRANSACTION_HASH"

    let final = try await portal.trading.lifi.pollStatus(
        request: LifiStatusRequest(
            txHash: txHash,
            fromChain: "eip155:8453",
            toChain: "eip155:42161"
        ),
        onUpdate: { update in
            print("Status: \(update.status.rawValue)")
            return true  // return false to stop polling early
        }
    )

    print("Final status: \(final.status.rawValue)")
} catch LifiTradeAssetError.pollTimeout {
    print("Timed out waiting for the transfer to settle")
} catch {
    print("pollStatus failed: \(error)")
}
```

With custom cadence:

```swift theme={null}
let txHash = "0xYOUR_TRANSACTION_HASH"

let final = try await portal.trading.lifi.pollStatus(
    request: LifiStatusRequest(txHash: txHash, fromChain: "eip155:8453", toChain: "eip155:42161"),
    options: LifiPollStatusOptions(everyMs: 5_000, initialDelayMs: 10_000, timeoutMs: 300_000)
)
```

**Related Documentation**

* [Bridge & Swap with Li.Fi](../guide/lifi)
* [tradeAsset](./lifitradeasset)
* [Li.Fi Integration](/integrations/Trading/lifi)
