# Core Features

### 1. Get Quote <a href="#get-quote" id="get-quote"></a>

Use `PeachClient.getQuote()` to retrieve a normalized `Quote`.

```ts
const quote = await client.getQuote({
  srcToken,
  dstToken,
  amountIn,
  options: {
    providers: ["PANCAKEV3", "UNISWAPV3"],    // optional — all 7 providers enabled by default
    deadlineSeconds: 1200,                    // optional — default 20 minutes
    customFee: {                              // optional — integrator (custom) fee
      feeAccount: "0xYourIntegratorWallet",   // optional - custom fee will transfer to feeAccount directly
      feeBps: 100,                            // optional - 1% — capped at MAX_FEE_BPS (500 bps = 5%)
    },
  },
});
```

**Parameters**

<table><thead><tr><th width="138.05859375">Field</th><th width="188.4921875">Type</th><th width="120.25390625">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>srcToken</code></td><td><code>string</code></td><td>Yes</td><td>Source token address</td></tr><tr><td><code>dstToken</code></td><td><code>string</code></td><td>Yes</td><td>Destination token address</td></tr><tr><td><code>amountIn</code></td><td><code>bigint</code></td><td>Yes</td><td>Input amount in wei</td></tr><tr><td><code>options</code></td><td><code>QuoteOptions</code></td><td>No</td><td>See options table below</td></tr></tbody></table>

**Options** (`QuoteOptions`)

<table><thead><tr><th width="155.2109375">Option</th><th width="205.90234375">Type</th><th width="134.14453125">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>depth</code></td><td><code>number</code></td><td><code>3</code></td><td>Route search depth / max hops</td></tr><tr><td><code>splitCount</code></td><td><code>number</code></td><td><code>20</code></td><td>Trade split count for large trades</td></tr><tr><td><code>providers</code></td><td><code>Provider[]</code></td><td>All 7 providers</td><td>DEX providers to query</td></tr><tr><td><code>deadlineSeconds</code></td><td><code>number</code></td><td><code>1200</code></td><td>Transaction deadline in seconds</td></tr><tr><td><code>customFee</code></td><td><code>CustomFee</code></td><td>NULL</td><td>Optional integrator (custom) fee taken from output. See Custom Fee below</td></tr></tbody></table>

**Returns** (`Quote`)

<table><thead><tr><th width="140.44921875">Field</th><th width="197.59765625">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>srcToken</code></td><td><code>string</code></td><td>Source token address</td></tr><tr><td><code>dstToken</code></td><td><code>string</code></td><td>Destination token address</td></tr><tr><td><code>amountIn</code></td><td><code>bigint</code></td><td>Input amount</td></tr><tr><td><code>amountOut</code></td><td><code>bigint</code></td><td>Expected output amount</td></tr><tr><td><code>priceImpact</code></td><td><code>number</code></td><td>Estimated price impact</td></tr><tr><td><code>gasEstimate</code></td><td><code>bigint</code></td><td>Estimated gas cost</td></tr><tr><td><code>route</code></td><td><code>SplitRoute</code></td><td>Split route data for display</td></tr><tr><td><code>params</code></td><td><code>SwapParams</code></td><td>Swap parameters for execution</td></tr><tr><td><code>routerAddress</code></td><td><code>string?</code></td><td>Router contract address from API</td></tr><tr><td><code>customFee</code></td><td><code>{ feeAccount, feeBps, feeAmount }?</code></td><td>Populated only when <code>options.customFee</code> was set. <code>feeAmount</code> is the <strong>total</strong> fee (integrator + protocol shares) in dstToken</td></tr></tbody></table>

### 2. Approve and Swap <a href="#approve-and-swap" id="approve-and-swap"></a>

Use `swap()` to build transactions without broadcasting them.

```ts
const prepared = await client.swap(
  quote, 
  ownerAddress, 
  {
    slippageBps: 50,
  }
);
```

**Parameters**

<table><thead><tr><th width="138.58984375">Field</th><th width="122.1015625">Type</th><th width="109.79296875">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>quote</code></td><td><code>Quote</code></td><td>Yes</td><td>Quote object from <code>getQuote()</code></td></tr><tr><td><code>ownerAddress</code></td><td><code>string</code></td><td>Yes</td><td>Wallet address for allowance check</td></tr><tr><td><code>options</code></td><td><code>SwapOptions</code></td><td>Yes</td><td>See options table below</td></tr></tbody></table>

**Options** (`SwapOptions`)

<table><thead><tr><th width="139.546875">Option</th><th width="93.859375">Type</th><th width="110.62109375">Required</th><th width="96.93359375">Default</th><th>Description</th></tr></thead><tbody><tr><td><code>slippageBps</code></td><td><code>number</code></td><td>Yes</td><td>—</td><td>Slippage tolerance in bps (e.g. 5 = 0.05%)</td></tr><tr><td><code>gasPrice</code></td><td><code>bigint</code></td><td>No</td><td>—</td><td>Gas price in wei</td></tr><tr><td><code>gasLimit</code></td><td><code>bigint</code></td><td>No</td><td>—</td><td>Gas limit for the swap tx</td></tr></tbody></table>

**Returns** (`SwapRequest`)

<table><thead><tr><th width="144.3828125">Field</th><th width="200.41796875">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>routerAddress</code></td><td><code>string</code></td><td>Router contract address</td></tr><tr><td><code>method</code></td><td><code>"swap" | "swapETH"</code></td><td>Call method</td></tr><tr><td><code>tx</code></td><td><code>SwapTxRequest</code></td><td>Swap transaction request (<code>to</code>, <code>data</code>, <code>value</code>)</td></tr><tr><td><code>approval</code></td><td><code>SwapApprovalRequest?</code></td><td>Included only when ERC20 allowance is insufficient</td></tr></tbody></table>

Send approval first when it exists, then send the swap transaction.

```ts
import { withWalletSendTimeout } from "@peachprojects/aggregator-sdk";

if (prepared.approval) {
  const approvalTx = await withWalletSendTimeout(
    signer.sendTransaction(prepared.approval.tx)
  );
  await approvalTx.wait();
}

const swapTx = await withWalletSendTimeout(signer.sendTransaction(prepared.tx));
await swapTx.wait();
```

`swap()` only prepares tx requests. Browser-wallet integrations should wrap their own `sendTransaction()` calls with timeout and recovery logic. `withWalletSendTimeout()` is the lightweight helper the SDK exposes for that path.

### Custom Fee <a href="#custom-fee" id="custom-fee"></a>

Pass `options.customFee` on `getQuote()` to charge an additional fee on top of the swap output. The on-chain router atomically takes the fee from the destination token (or native BNB when `dstToken` is native) and forwards the integrator's share to `feeAccount`.

```ts
const quote = await client.getQuote({
  srcToken,
  dstToken,
  amountIn,
  options: {
    customFee: {
      feeAccount: "0xYourIntegratorWallet",
      feeBps: 100, // 1% — capped at MAX_FEE_BPS (500 bps = 5%)
    },
  },
});
```

**`CustomFee` parameters**

<table><thead><tr><th width="125.1875">Field</th><th width="87.5859375">Type</th><th width="110.44921875">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>feeAccount</code></td><td><code>string</code></td><td>Yes</td><td>Address that receives the integrator's share. Must be a valid non-zero address; the router additionally rejects <code>feeAccount == router</code> and <code>feeAccount == msg.sender</code></td></tr><tr><td><code>feeBps</code></td><td><code>number</code></td><td>Yes</td><td>Total custom fee in basis points (1 bps = 0.01%). Must be an integer in <code>[1, MAX_FEE_BPS]</code> (500 = 5%). The contract cap is owner-settable — read it live via <code>getRouterConfig()</code></td></tr></tbody></table>

The Peach protocol takes a configurable share of `feeBps` (default 20%, capped on-chain by the owner-settable `maxProtocolCutBps`). The remainder is forwarded to `feeAccount`. To preview the integrator / protocol split before signing, read the live values via:

* `client.getRouterConfig()` — full router snapshot (address, WETH, owner, paused, fee caps, current split)
* `client.getProtocolFeeConfig()` — just the receiver and `protocolCutBps`

```ts
const cfg = await client.getProtocolFeeConfig();
if (quote.customFee) {
  const total = quote.customFee.feeAmount;
  const protocolShare = (total * BigInt(cfg.protocolCutBps)) / 10_000n;
  const integratorShare = total - protocolShare;
}
```

### Native and ERC20 Handling <a href="#native-and-erc20-handling" id="native-and-erc20-handling"></a>

* Native BNB input does not require approval
* ERC20 input may require approval — `swap()` checks allowance automatically
* Native BNB uses `swapETH`; ERC20 uses `swap`
* Native BNB in the SDK is represented by `NATIVE_TOKEN_ADDRESS` (`0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.peach.ag/documentation/editor.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
