> ## 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.

# tradeAsset

> Runs an end-to-end Li.Fi bridge or swap in a single call.

**Function Signature**

```swift theme={null}
public func tradeAsset(params: LifiTradeAssetParams) async throws -> LifiTradeAssetResult
```

**Description**

Executes a complete Li.Fi bridge or swap: discovers routes, selects one, then for each step builds the transaction, signs and broadcasts it, waits for on-chain confirmation, and polls Li.Fi until that step reaches a terminal state before moving to the next.

Steps run **sequentially**. Signing and confirmation for each step happen on that step's own chain, resolved from the step itself, so a multi-chain route is handled without the caller switching networks.

Confirmation is strict — every step must confirm on-chain before the next begins. A revert or a confirmation timeout aborts the trade and throws. There is no optimistic fallback.

Unlike the React Native and Web SDKs, there is no second options argument. The signer and confirmation hooks are injected when the `Lifi` instance is constructed, and `Portal` wires both automatically.

**Parameters**

`LifiTradeAssetParams`:

| Parameter     | Type                   | Required        | Description                                                                               |
| ------------- | ---------------------- | --------------- | ----------------------------------------------------------------------------------------- |
| `fromChain`   | `String`               | Yes             | Source chain, CAIP-2 (`"eip155:8453"`).                                                   |
| `toChain`     | `String`               | Yes             | Destination chain, CAIP-2.                                                                |
| `fromToken`   | `String`               | Yes             | Source token contract address or symbol.                                                  |
| `toToken`     | `String`               | Yes             | Destination token contract address or symbol.                                             |
| `amount`      | `String`               | Yes             | Amount in the token's base units, as an integer string.                                   |
| `fromAddress` | `String?`              | No, but pass it | Sending wallet address. Forwarded to Li.Fi as given; the SDK does not resolve it for you. |
| `toAddress`   | `String?`              | No              | Receiving wallet address. Falls back to `fromAddress`.                                    |
| `routeIndex`  | `Int?`                 | No              | Which discovered route to execute. Default `0`.                                           |
| `onProgress`  | `LifiProgressHandler?` | No              | Callback fired at each stage of execution.                                                |

<Warning>
  Omitting `fromAddress` means routes are quoted without a sender while the transaction is still signed by your Portal wallet, so the quote may not match what executes. Pass it explicitly.
</Warning>

**Returns**

**`LifiTradeAssetResult`**:

| Property | Type         | Description                                                                 |
| -------- | ------------ | --------------------------------------------------------------------------- |
| `hashes` | `[String]`   | One transaction hash per executed step, in execution order.                 |
| `steps`  | `[LifiStep]` | The enriched steps that were executed, with `transactionRequest` populated. |
| `route`  | `LifiRoute`  | The route that was selected and executed.                                   |

**Throws**

Throws `LifiTradeAssetError`:

| Case                                      | When                                                                                   |
| ----------------------------------------- | -------------------------------------------------------------------------------------- |
| `missingSigner`                           | No signing closure on the `Lifi` instance. Cannot occur on `portal.trading.lifi`.      |
| `missingConfirmation`                     | No confirmation closure on the `Lifi` instance. Cannot occur on `portal.trading.lifi`. |
| `noRoutesFound`                           | Li.Fi returned no routes for the requested trade.                                      |
| `routeIndexOutOfBounds`                   | `routeIndex` is negative or beyond the number of discovered routes.                    |
| `routeHasNoSteps`                         | The selected route contains no steps.                                                  |
| `missingTransactionRequest`               | A step came back without a transaction request to sign.                                |
| `invalidTransactionRequest`               | A step's transaction request was malformed.                                            |
| `transactionConfirmationFailed(String)`   | The step's transaction reverted on-chain. Carries the transaction hash.                |
| `transactionConfirmationTimedOut(String)` | Confirmation could not be determined before timing out. Carries the transaction hash.  |
| `lifiTransferFailed(String)`              | Li.Fi reported a `FAILED` terminal state.                                              |
| `pollTimeout`                             | Status polling exceeded the configured timeout.                                        |

Also throws `CancellationError` if the surrounding `Task` is cancelled. In that case **no `.failed` progress event is emitted** — handle cancellation separately from failure.

**Example Usage**

```swift theme={null}
import PortalSwift

do {
    let fromAddress = try await portal.getAddress("eip155:8453")

    let result = try await portal.trading.lifi.tradeAsset(
        params: LifiTradeAssetParams(
            fromChain: "eip155:8453",
            toChain: "eip155:42161",
            fromToken: "ETH",
            toToken: "USDC",
            amount: "1000000000000",
            fromAddress: fromAddress,
            onProgress: { status, data in
                print("[Li.Fi] \(status.rawValue) \(data.txHash ?? "")")
            }
        )
    )

    print("Hashes: \(result.hashes)")
    print("Executed steps: \(result.steps.count)")
} catch let LifiTradeAssetError.transactionConfirmationFailed(txHash) {
    print("Transaction reverted on-chain: \(txHash)")
} catch {
    print("tradeAsset failed: \(error)")
}
```

**Related Documentation**

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