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

# Quotes & Swaps

> Fetch quotes, stream them in real time, execute swaps, and track transactions

## Fetch a Quote

```typescript theme={null}
const quote = await sdk.getQuote({
  fromAsset: "ETH.ETH",
  toAsset: "BTC.BTC",
  amount: "1000000000000000000",   // 1 ETH in wei
  destination: "bc1q...",
  origin: "0x...",                 // optional, improves accuracy
  slippageBps: 150,                // optional, 1.5%
});
```

The returned `SwapQuote` includes the cheapest/fastest route across all enabled protocols, plus `quoteId` (used for subsequent `executeSwap` and tracking calls).

`AbortSignal` is supported for cancellation:

```typescript theme={null}
const ctrl = new AbortController();
setTimeout(() => ctrl.abort(), 5000);
const q = await sdk.getQuote(params, ctrl.signal);
```

## Stream Quotes

For UI use cases — display the first quote in \~200ms instead of waiting for every protocol:

```typescript theme={null}
const stop = sdk.streamQuote(
  { fromAsset: "ETH.ETH", toAsset: "BTC.BTC", amount: "1000000000000000000" },
  {
    onInit:   (e) => console.log("quote_id:", e.quoteId),
    onQuote:  (e) => console.log(e.protocol, e.data.expected_amount_out),
    onComplete: (e) => console.log("best:", e.quotes[0]),
    onError:  (e) => console.error(e.code, e.message),
  }
);

// Optional: cancel mid-stream
stop();
```

`StreamQuoteCallbacks` exposes typed events: `StreamingQuoteInitEvent`, `StreamingQuoteQuoteEvent`, `StreamingQuoteFinalEvent`, `StreamingQuoteErrorEvent`, `StreamingQuoteFinishedEvent`.

The streaming endpoint is documented at [Streaming Quotes](/api-reference/endpoint/streaming-quotes).

## Execute a Swap

```typescript theme={null}
const result = await sdk.executeSwap(quote, {
  // SwapOptions — all optional
  feeOption: "fast",          // fee tier hint (chain-dependent)
  preferredProtocol: "thorchain", // pin a route from the quote bundle
});
```

`SwapResult` contains `txHash` (or `txHashes` for multi-tx flows like ERC20 approve + swap), the chosen `protocol`, and any `depositInstruction` data.

ERC20 approvals are auto-handled when needed. The SDK inserts the approval transaction first, then the swap. See the [ERC20 approvals guide](/guides/erc20-approvals) for details.

## Plain Transfer (no swap)

`sdk.transfer()` sends native or token assets directly without going through a protocol:

```typescript theme={null}
const tx = await sdk.transfer({
  asset: "ETH.USDC-0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
  amount: "100",      // 100 USDC
  to: "0xrecipient...",
});
// TransferResult { txHash }
```

Useful when your app needs simple "move funds" capability that's not part of a swap.

## Transaction Lifecycle

After broadcasting, save the hash so the LeoKit backend can track and emit webhooks:

```typescript theme={null}
await sdk.saveTransaction(quote.quoteId, result.txHash);
```

Poll once:

```typescript theme={null}
const status = await sdk.getTransactionStatus(quote.quoteId);
// TransactionStatus { state: "pending" | "success" | "failed" | "refunded", ... }
```

Or watch with backoff:

```typescript theme={null}
const stop = sdk.watchTransaction(quote.quoteId, (status) => {
  if (status.state !== "pending") stop();
}, { intervalMs: 5000, maxIntervalMs: 30000 });
```

`watchTransaction` polls `/leokit/status` and exits cleanly when the swap settles or fails.

## Assets & Balances

```typescript theme={null}
const all = await sdk.getAssets();             // Asset[]
const usdc = await sdk.getAsset("ETH.USDC-0xA0b...");

await sdk.refreshAssets();                     // forces re-fetch

const bal = await sdk.getBalance("ETH.ETH");           // single
const all = await sdk.getAllBalances();                // every connected wallet × every chain
const slim = await sdk.getBalancesForAddresses([
  { chain: "ETH", address: "0x..." },
  { chain: "BTC", address: "bc1q..." },
]);
```

The asset list is cached for 20 seconds (per-client); `refreshAssets()` bypasses the cache.

## Events

```typescript theme={null}
sdk.on("transaction", (e) => console.log(e.quoteId, e.state));
sdk.on("walletChange", (e) => console.log(e.from, "→", e.to));
sdk.on("error", (err) => console.error(err));
```

`LeoKitEvents` is fully typed. Listeners can be removed via the returned `Unsubscribe` function or `sdk.off("transaction", listener)`.
