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

# Swap Tokens with 0x

> Learn how to swap tokens using Portal's React Native SDK with 0x integration.

Portal's React Native SDK provides high-level 0x swaps through
`portal.trading.zeroX.tradeAsset(...)`.

## Overview

Using the high-level 0x flow, you can:

* **Trade assets end-to-end** with one call
* **Track lifecycle progress** from quote fetch to confirmation
* **Override signer and confirmation behavior** per call when needed

<Note>
  **0x vs Li.Fi:**

  * **0x**: Best for **same-chain** token swaps. Executes one transaction with fast, simple chain confirmation. No cross-chain routing.
  * **Li.Fi**: Best for **cross-chain** bridges and swaps. Handles multi-step routes (bridge + swap) with protocol-level status tracking.
</Note>

## Prerequisites

Before using the 0x API, make sure you have:

* A properly initialized Portal client
* An active wallet with sufficient balance on the source network
  (see [Create a wallet](./create-a-wallet))
* 0x integration enabled in your Portal Dashboard (see [0x Integration](../../../integrations/Trading/zerox)) OR have a 0x API Key available

***

## High-Level Methods

### `tradeAsset`

Fetches a 0x quote, signs and broadcasts the quote transaction, waits for on-chain confirmation, and returns hashes.

### Signature

```typescript theme={null}
tradeAsset(
  params: ZeroXTradeAssetParams,
  options?: ZeroXTradeAssetOptions,
): Promise<ZeroXTradeAssetResult>
```

**Essential parameters**

| Name                                             | Required | Description                                                                                   |
| ------------------------------------------------ | -------- | --------------------------------------------------------------------------------------------- |
| `chainId`                                        | Yes      | CAIP-2 chain (e.g. `'eip155:1'`). See [Supported Networks](#supported-networks).              |
| `sellToken`                                      | Yes      | Token to sell (symbol or address).                                                            |
| `buyToken`                                       | Yes      | Token to buy (symbol or address).                                                             |
| `sellAmount`                                     | Yes      | Amount in base units (smallest units).                                                        |
| `fromAddress`                                    | No       | Sender address used by high-level 0x execution.                                               |
| `slippageBps`                                    | No       | Max slippage in basis points (e.g. `100` = 1%).                                               |
| `swapFeeRecipient`, `swapFeeBps`, `swapFeeToken` | No       | Integrator fee fields.                                                                        |
| `tradeSurplusRecipient`                          | No       | Surplus recipient.                                                                            |
| `gasPrice`                                       | No       | Optional gas price.                                                                           |
| `excludedSources`                                | No       | Comma-separated sources to exclude.                                                           |
| `sellEntireBalance`                              | No       | `'true'` / `'false'`.                                                                         |
| `onProgress`                                     | No       | Stages such as `fetching_quote`, `signing`, `submitted`, `confirming`, `confirmed`, `failed`. |
| `zeroXApiKey`                                    | No       | Override the Dashboard key for this call.                                                     |

`ZeroXTradeAssetOptions`:

| Name                     | Required | Description                                                                                                                                                                    |
| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `signAndSendTransaction` | No       | Per-call signer override.                                                                                                                                                      |
| `waitForConfirmation`    | No       | Per-call confirmation override. **MUST return `true` or resolve for success.** Returning `false`, throwing an error, or timing out will **abort the swap** and throw an error. |

**Return value**

| Field    | Description                   |
| -------- | ----------------------------- |
| `hashes` | Broadcast transaction hashes. |

<Note>
  0x `tradeAsset` follows Yield-style execution precedence:

  * **Signer**: per-call `options.signAndSendTransaction` -> instance default signer -> throw
  * **Confirmation**: per-call `options.waitForConfirmation` -> instance default waiter -> throw

  Confirmation is strict: if the waiter returns `false`, times out, throws an error, or the network is unsupported, the swap fails immediately.
</Note>

**Example (`onProgress` + default on-chain wait)**

```typescript theme={null}
import Portal from '@portal-hq/core'
import type { ZeroXTradeAssetParams } from '@portal-hq/core'

const portal = new Portal({
  apiKey: 'YOUR_PORTAL_CLIENT_API_KEY',
  backup: {
    /* ... */
  },
  gatewayConfig: { 'eip155:1': 'https://YOUR_RPC_URL' },
})

async function swap() {
  const eip155Address = await portal.address
  if (!eip155Address) throw new Error('No EVM address')

  const params: ZeroXTradeAssetParams = {
    chainId: 'eip155:1',
    sellToken: 'ETH',
    buyToken: 'USDC',
    sellAmount: '100000000000000',
    fromAddress: eip155Address,
    onProgress: (status, data) => {
      console.log('[0x]', status, data.txHash ?? '', data.errorMessage ?? '')
    },
  }

  try {
    const result = await portal.trading.zeroX.tradeAsset(params)
    console.log('Hashes:', result.hashes)
    return result
  } catch (e) {
    console.error('tradeAsset failed', e)
    throw e
  }
}
```

Use `try/catch` around `tradeAsset`; `onProgress` may emit `failed` before the thrown error.

***

## Example (custom API key + execution options)

```typescript theme={null}
const result = await portal.trading.zeroX.tradeAsset(
  {
    chainId: 'eip155:1',
    sellToken: 'ETH',
    buyToken: 'USDC',
    sellAmount: '100000000000000',
    fromAddress: await portal.address,
    zeroXApiKey: 'YOUR_0X_API_KEY',
    onProgress: (status, data) => {
      console.log('[0x]', status, data.txHash ?? '', data.errorMessage ?? '')
    },
  },
  {
    waitForConfirmation: async (txHash, network) => {
      return portal.waitForConfirmation(txHash, network)
    },
  },
)

console.log(result.hashes)
```

***

## Using a Custom 0x API Key (Optional)

By default, Portal uses the 0x API Key that can be added through the Portal Dashboard to communicate with the 0x integration.

```ts theme={null}
import { ZeroXQuoteRequest } from '@portal-hq/trading'

const request: ZeroXQuoteRequest = {
  chainId: 'eip155:1',
  sellToken: 'ETH',
  buyToken: 'USDC',
  sellAmount: '100000000000000', // 0.0001 ETH
}

const response = await portal.trading.zeroX.getQuote(request)
console.log('Quote received:', response.data?.rawResponse)

```

If you have a 0x API key that you want to test with locally, you can optionally include it in the request body via the options parameter.

```ts theme={null}
await portal.trading.zeroX.getQuote(request, {
  zeroXApiKey: 'YOUR_0X_API_KEY',
})

```

***

## Getting a Price (Indicative)

Use `portal.trading.zeroX.getPrice` to retrieve an **indicative price** for a
token swap without generating executable transaction data.

This method is useful for displaying prices, estimating swap outcomes, or
building preview experiences without committing to a quote.

```ts theme={null}
import { ZeroXPriceRequest } from '@portal-hq/trading'

async function getZeroXPrice(portal: Portal) {
  const request: ZeroXPriceRequest = {
    chainId: 'eip155:1',
    sellToken: 'USDT',
    buyToken: 'USDC',
    sellAmount: '100000000000000000000000', // 100,000 USDT in wei
  }

  const response = await portal.trading.zeroX.getPrice(request)

  if (response.error) {
    console.error('ZeroX error:', response.error)
    return
  }

  const price = response.data?.rawResponse
}
```

***

## Getting a Swap Quote

Use `portal.trading.zeroX.getQuote` to fetch a swap quote from 0x.

```ts theme={null}
import { ZeroXQuoteRequest, ZeroXTransactionRequest } from '@portal-hq/trading'

async function getZeroXQuote(portal: Portal) {
  const takerAddress = await portal.getAddress('eip155:1')

  const request: ZeroXQuoteRequest = {
    chainId: 'eip155:1',
    sellToken: 'ETH',
    buyToken: 'USDC',
    sellAmount: '1000000000000000000',
  }

  const response = await portal.trading.zeroX.getQuote(request)

  if (response.error) {
    console.error('ZeroX error:', response.error)
    return
  }

  const quote = response.data?.rawResponse

  if (!quote?.transaction) {
    return
  }

  const transaction: ZeroXTransactionRequest = {
    from: takerAddress,
    to: quote.transaction.to,
    value: quote.transaction.value ?? '0x0',
    data: quote.transaction.data,
    gas: quote.transaction.gas,
    gasPrice: quote.transaction.gasPrice,
  }

  return transaction
}
```

***

## Getting Liquidity Sources

You can query available liquidity sources supported by 0x using
`portal.trading.zeroX.getSources`.

For full request and response details, refer to the Client API documentation.

```ts theme={null}
async function getZeroXSources(portal: Portal) {
  const response = await portal.trading.zeroX.getSources('eip155:1', {
    zeroXApiKey: 'YOUR_KEY',
  })

  if (response.error) {
    console.error('ZeroX error:', response.error)
    return
  }

  const sources = response.data?.rawResponse
}
```

***

## Executing the Swap

Once you receive a quote containing transaction data, execute the swap by
sending the transaction through `portal.request`.

> **Note**\
> The transaction data returned by 0x may include gas parameters such as
> `gas` or `gasPrice`. These fields are optional — you can omit them and let
> Portal estimate gas automatically, or include them if you prefer to use
> 0x's suggested values.

```ts theme={null}
import { ETHTransactionParam } from '@portal-hq/provider'
import { ZeroXTransactionRequest } from '@portal-hq/trading'

async function executeSwap(
  portal: Portal,
  transaction: ZeroXTransactionRequest,
  chainId: string
) {
  const ethTx: ETHTransactionParam = {
    from: transaction.from,
    to: transaction.to,
    value: transaction.value ?? '0x0',
    data: transaction.data,
    gas: transaction.gas,
    gasPrice: transaction.gasPrice,
  }

  const response = await portal.request(
    chainId,
    'eth_sendTransaction',
    [ethTx]
  )
}
```

***

## Supported Networks

The `portal.trading.zeroX` API supports a predefined set of EIP-155 networks.
Requests using unsupported chains will fail.

| Network       | EIP-155 Chain ID |
| ------------- | ---------------- |
| Ethereum      | `eip155:1`       |
| Optimism      | `eip155:10`      |
| BSC           | `eip155:56`      |
| Unichain      | `eip155:130`     |
| Polygon       | `eip155:137`     |
| Monad         | `eip155:143`     |
| Worldchain    | `eip155:480`     |
| Mantle        | `eip155:5000`    |
| Base          | `eip155:8453`    |
| Monad Testnet | `eip155:10143`   |
| Mode          | `eip155:34443`   |
| Arbitrum      | `eip155:42161`   |
| Avalanche     | `eip155:43114`   |
| Ink           | `eip155:57073`   |
| Linea         | `eip155:59144`   |
| Berachain     | `eip155:80094`   |

***

## Next Steps

* Learn how to [sign Ethereum transactions](./sign-a-transaction)
* Explore how to [send tokens](./send-tokens)
* Review the [Client API 0x endpoints](../../../apis/client/api-reference-link)
