# Get Swap Quote

Step 1 of every swap — get a LI.FI route for a wallet, together with the `transactionData` you will execute.

## Overview

Aurea requests the quote from the **LI.FI** aggregator for the wallet identified by `walletId`, which must belong to the authenticated user. The response carries a `quoteId`, the estimated output (`toAmount`, `toAmountMin`), approval information (`approvalAddress`, `needsApproval`) and a `transactionData` object. Pass `quoteId` and `transactionData` unchanged to [Execute Swap](https://docs.aureahub.com/docs/swap-execute.md).

- **Chains** — `fromChain` and `toChain` must be one of `ethereum`, `polygon`, `gnosis`, `bsc`, `arbitrum`, `optimism`, `base`, `avalanche`, `celo`, `flowevm`, `solana`.
- **Tokens** — both tokens must be present in Aurea's token registry for their chain (see [Tokens by Chain](https://docs.aureahub.com/docs/tokens-by-chain.md)). Use the zero address `0x0000000000000000000000000000000000000000` for an EVM chain's native coin. On Solana, `So11111111111111111111111111111111111111112` and `11111111111111111111111111111111` are both treated as native SOL.
- **Slippage** — `slippage` is a **percentage** (`0.5` = 0.5%). There is no `slippage_bps` field; the body schema does not allow additional properties.
- **Destination** — without `toAddress`, a same-chain swap pays out to the source wallet. For a cross-chain swap Aurea uses the user's primary wallet on `toChain`. For an EVM destination without one, it falls back to another of the user's EVM wallets. For a Solana destination it uses the user's existing Solana wallet and, if there is none, **creates one during the quote call**.
- **Rejected routes** — Aurea refuses routes that would deliver a different token than `toToken`, and routes that need a second signature on the destination chain. `requiresDestinationSignature` is therefore always `false` in a successful response.

> ⚠️ **Testnet quotes are rejected.** The API's list of LI.FI-supported testnet chains is empty, so a quote with `isTestnet: true` fails with `400`. To exercise swap UI and history on testnet, use [Simulate Swap](https://docs.aureahub.com/docs/swap-simulate.md).

## Swap Flow

1. **Get Quote** — this endpoint.
2. **Approve** (EVM ERC-20 source tokens, when `needsApproval` is `true`) — [Approve Token](https://docs.aureahub.com/docs/swap-approve.md) with `spenderAddress` set to `approvalAddress`. Non-custodial wallets then sign and call [Broadcast Approve Tx](https://docs.aureahub.com/docs/swap-broadcast-approve.md).
3. **Execute** — [Execute Swap](https://docs.aureahub.com/docs/swap-execute.md) with `quoteId` and `transactionData`. Non-custodial EVM wallets then sign and call [Broadcast Swap Tx](https://docs.aureahub.com/docs/swap-broadcast.md).
4. **Track** — poll [Get Tx Status](https://docs.aureahub.com/docs/tx-status.md) with the returned `transactionId` while the status is `pending`.

> ℹ️ When the response contains a `gasless` object (EUR.e → xDAI on Gnosis), you can use the permit-based flow instead: [Sign EIP-712 Permit](https://docs.aureahub.com/docs/swap-sign-permit.md), then [Execute Gasless](https://docs.aureahub.com/docs/swap-gasless.md). The [Token Swaps guide](https://docs.aureahub.com/docs/guide-swap.md) walks through every flow end to end.

## Endpoint

### `POST /v1/swap/quote`

Authentication: bearer token required.

Returns a LI.FI route, the estimated output, approval information and the transaction data to execute.

**Request body**

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `walletId` | string (uuid) | yes | Source wallet. Must belong to the authenticated user. |
| `fromChain` | string | yes | Source chain name, e.g. `polygon`. |
| `toChain` | string | yes | Destination chain name. Same value as `fromChain` for a same-chain swap. |
| `fromToken` | string | yes | Source token address: `0x` + 40 hex characters, or a Solana base58 address (32–44 characters). |
| `toToken` | string | yes | Destination token address, same format as `fromToken`. |
| `fromAmount` | string | yes | Amount to swap; must match `^\d+(\.\d+)?$`. Aurea forwards it to LI.FI as `fromAmount` without converting it — it is not scaled by token decimals. |
| `slippage` | number | no | Maximum slippage as a **percentage**, from 0 to 50 — `0.5` means 0.5%. Defaults to `0.5`. Aurea divides the value by 100 before sending it to LI.FI. |
| `toAddress` | string | no | Address that receives the output. When omitted, Aurea resolves the destination as described in the Overview. |
| `isTestnet` | boolean | no | Use testnet chain IDs. Defaults to `false`. Currently rejected — see the warning above. |

**Responses**

`200` OK

```json
{
  "quoteId": "…",
  "isTestnet": false,
  "sourceChainType": "evm",
  "fromChain": "polygon",
  "fromChainId": 137,
  "toChain": "polygon",
  "toChainId": 137,
  "fromToken": { "address": "0x…", "symbol": "…", "decimals": 6, "name": "…" },
  "toToken": { "address": "0x0000000000000000000000000000000000000000", "symbol": "…", "decimals": 18, "name": "…" },
  "fromAmount": "…",
  "toAmount": "…",
  "toAmountMin": "…",
  "tool": "…",
  "approvalAddress": "0x…",
  "needsApproval": true,
  "estimatedGas": "…",
  "estimatedGasCostWei": "…",
  "estimatedGasCostNative": "…",
  "nativeTokenSymbol": "MATIC",
  "nativeTokenBalance": "…",
  "transactionValueNative": "…",
  "totalCostRequired": "…",
  "sufficientBalance": true,
  "executionTime": 30,
  "transactionData": { "to": "0x…", "data": "0x…", "value": "0", "gasLimit": "…" },
  "requiresDestinationSignature": false
}
```

`400` Bad Request

```json
{
  "statusCode": 400,
  "error": "BadRequestError",
  "message": "No swap route is available for this token pair at the moment. Try a different token, a different amount, or check back later."
}
```

`401` Unauthorized

```json
{
  "statusCode": 401,
  "error": "UnauthorizedError",
  "message": "Authentication required"
}
```

`404` Not Found

```json
{
  "statusCode": 404,
  "error": "NotFoundError",
  "message": "Wallet not found"
}
```

Values shown as `…` depend on the quote; the other example values are illustrative.

## Response Fields

- `quoteId` — LI.FI's quote id. Send it to Execute Swap, which stores it with the transaction.
- `sourceChainType` — `evm` or `solana`; tells you which execution path applies.
- `fromChainId`, `toChainId` — numeric chain IDs resolved by Aurea (Solana: `1399811149` mainnet, `1399811150` devnet).
- `fromToken`, `toToken` — `{ address, symbol, decimals, name }` as returned by LI.FI.
- `fromAmount`, `toAmount`, `toAmountMin` — LI.FI's estimate, as strings.
- `tool` — name of the LI.FI tool (bridge or exchange) used by the route.
- `approvalAddress` — the spender to approve. `null` for native source tokens, for Solana sources, and when LI.FI returns no approval address.
- `needsApproval` — `true` only when the wallet's current allowance for `approvalAddress` is exactly `0`. It is not compared with `fromAmount`.
- `estimatedGas` — gas units from LI.FI (`"0"` when LI.FI gives none).
- `estimatedGasCostWei`, `estimatedGasCostNative`, `nativeTokenSymbol`, `transactionValueNative`, `totalCostRequired` — optional; omitted when there is no gas estimate or the gas price cannot be fetched. `nativeTokenBalance` and `sufficientBalance` are also omitted when the balance cannot be fetched. `sufficientBalance` is `true` when the native balance covers `totalCostRequired`.
- `executionTime` — LI.FI's estimated execution duration.
- `transactionData` — `{ to, data, value, gasLimit }`. For a Solana source, `data` holds the base64-encoded `VersionedTransaction`.
- `requiresDestinationSignature` — always `false`.
- `priceImpact` — declared in the response schema but not populated by the current implementation.
- `gasless` — present only when gasless swaps are enabled on the deployment and the quote is EUR.e → native xDAI on Gnosis (both chains `gnosis`, `toToken` the zero address). `estimatedGasCost` is in wei.

```json
{
  "gasless": {
    "supported": true,
    "permitRequired": true,
    "estimatedGasCost": "…",
    "estimatedGasCostXDAI": "0.000123",
    "currentNonce": 0,
    "permitDomain": {
      "name": "Monerium EURe",
      "version": "1",
      "chainId": 100,
      "verifyingContract": "0x420CA0f9B9b604cE0fd9C18EF134C705e5Fa3430"
    }
  }
}
```

## Errors

Errors use the shape `{ statusCode, error, message }`, with `details` when available.

- `400` `Request validation failed` — the body does not match the schema (`details` lists the problems).
- `400` `Unsupported chain: …` — the chain name is not in the list above.
- `400` `LI.FI does not support mainnet chain IDs: …` (or `testnet chain IDs`).
- `400` `Token not found: … on … mainnet. Please ensure the token is supported on this network.`
- `400` `No swap route is available for this token pair at the moment. …` — LI.FI error code 1002. Other LI.FI errors return `Unable to get a swap quote. Please try again or use a different token pair.`
- `400` `No direct route is available for the requested token pair. …` — the route would deliver a different token.
- `400` `No single-transaction route is available for this swap. …` — the route needs a signature on the destination chain.
- `400` `Failed to check token allowance` or `Network mismatch: …` — the allowance lookup for `needsApproval` failed.
- `404` `Wallet not found` — unknown wallet, or it belongs to another user.
- `404` `No primary … wallet found for this user. …` — no destination could be resolved for a cross-chain swap; pass `toAddress`.

## Implementation

```javascript
// Step 1: get a swap quote
async function getSwapQuote(token, { walletId, fromChain, toChain, fromToken, toToken, fromAmount, slippage = 0.5 }) {
  const res = await fetch('https://api.aureahub.com/v1/swap/quote', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'Authorization': `Bearer ${token}`
    },
    body: JSON.stringify({
      walletId,
      fromChain,
      toChain,
      fromToken,
      toToken,
      fromAmount,   // string, forwarded to LI.FI unchanged
      slippage      // percent: 0.5 = 0.5%
    })
  });

  const body = await res.json();
  if (!res.ok) throw new Error(`${res.status}: ${body.message}`);

  // Keep quoteId and transactionData for Execute Swap
  return body;
}
```

---

Web version: https://docs.aureahub.com/#swap-quote
