# Features Available

## 1. Find router

Func `client.findRouters()`

{% hint style="success" %}
**Aggregator Client v2 (v0.x.x) vs v3 (v1.x.x) Compatibility:**

* **Input**: The `findRouterInput` parameter structure is identical for both versions
* **Output Changes**: v3 replaces the `router` field with `paths`
* **Optimization**: v3 consolidates duplicate pools in the response, resulting in significant gas savings for multi-path routes
  {% endhint %}

### Params

#### Required parameters

<table><thead><tr><th width="146">Name</th><th width="155.81640625">Type</th><th width="463.23828125">Details</th></tr></thead><tbody><tr><td><strong>from</strong></td><td>String</td><td>The coin type of input coin.</td></tr><tr><td><strong>target</strong></td><td>String</td><td>The coin type of output coin.</td></tr><tr><td><strong>amount</strong></td><td>BN | string | number| bigint</td><td>The amount of input or output,determined <code>byAmountIn</code></td></tr><tr><td><strong>byAmountIn</strong></td><td>Boolean</td><td><code>true</code> means fixed the amount of input, <code>false</code> means fixed the amount of output.</td></tr></tbody></table>

#### Optional parameters

{% hint style="warning" %}
In principle, we do not recommend adding these optimal parameters if you don't have any specific custon needs, because our aggregator service will automatically optimize these settings in each SDK update to pursue optimal pricing and performance of transactions.
{% endhint %}

<table><thead><tr><th width="162">Name</th><th>Type</th><th width="450">Details</th></tr></thead><tbody><tr><td><strong>providers</strong></td><td>String Array</td><td>Now, support cetus,  deepbook v2/v3, kriya v2/v3, flowx v2/v3, aftermath, turbos, afsui, volo, haedal, bluemove, scallop, suilend, bluefin. If not set, it's will default support best providers by sdk version.</td></tr><tr><td><strong>depth</strong></td><td>Number</td><td>now depths support betweent 1 and 3, default setting is 3, it means you can get 3 hops path. </td></tr><tr><td><strong>splitAlgorithm</strong></td><td>String</td><td>devide_equally or geometric, recommand just use default devide_equally.</td></tr><tr><td><strong>splitFactor</strong></td><td>Number</td><td>used to contral geometric split width.</td></tr><tr><td><strong>splitCount</strong></td><td>Number</td><td>this field represents the maximum number of splits for a transaction. If you do not want to split, set it to 1. The default value is 20.</td></tr></tbody></table>

### **ResponseV3**

When using Aggregator SDK v3 (version 1.0.0 or higher), the `findRouter` method will return data in the RouterV3 structure.

<table><thead><tr><th width="180.453125">Name</th><th width="182.91796875">Type</th><th width="450">Details</th></tr></thead><tbody><tr><td><strong>quoteID</strong></td><td>string</td><td>A randomly generated ID from the aggregator service for tracking index transactions and quotes.</td></tr><tr><td><strong>amountIn</strong></td><td>BN</td><td>Total amount in.</td></tr><tr><td><strong>amountOut</strong></td><td>BN</td><td>Total amount out.</td></tr><tr><td><strong>byAmountIn</strong></td><td>Boolean</td><td><code>true</code> means fixed the amount of input, <code>false</code> means fixed the amount of output. This is the same as request parameters.</td></tr><tr><td><strong>paths</strong></td><td>Path[]</td><td>All liquidity paths data.</td></tr><tr><td><strong>insufficientLiquidity</strong></td><td>Boolean</td><td><code>true</code> means liquidity insufficient, <code>false</code> means liquidity enough.</td></tr><tr><td><strong>deviationRatio</strong></td><td>Number</td><td><mark style="color:red;">Price deviation ratio, (0.01 means 1%),  indicating the degree of difference between the aggregator result and market price. When the price deviation ratio is undefined (no reference market price available) or relatively large (significant deviation from existing market prices), provide users with a reference option on whether to execute the trade at the current price to avoid potential asset losses.</mark></td></tr><tr><td><strong>packages</strong></td><td>Map&#x3C;string, string></td><td>When user pass new version parameters, it will return  newest aggregator packages data.</td></tr><tr><td><strong>overlayFee</strong></td><td>Number</td><td>The amount for overlay fee.</td></tr><tr><td><strong>totalDeepFee</strong></td><td>Number</td><td>Calculated need deep fee for deep pools.</td></tr><tr><td><strong>error</strong></td><td>RouterError</td><td>Error code and msg for aggregator.</td></tr></tbody></table>

#### ResponseV2

<table><thead><tr><th width="180.453125">Name</th><th width="182.91796875">Type</th><th width="450">Details</th></tr></thead><tbody><tr><td>quoteID</td><td>string</td><td>A randomly generated ID from the aggregator service for tracking index transactions and quotes.</td></tr><tr><td><strong>amountIn</strong></td><td>BN</td><td>Total amount in.</td></tr><tr><td><strong>amountOut</strong></td><td>BN</td><td>Total amount out.</td></tr><tr><td><strong>byAmountIn</strong></td><td>Boolean</td><td><code>true</code> means fixed the amount of input, <code>false</code> means fixed the amount of output. This is the same as request parameters.</td></tr><tr><td><strong>routes</strong></td><td>Router[]</td><td>All liquidity routes data.</td></tr><tr><td><strong>insufficientLiquidity</strong></td><td>Boolean</td><td><code>true</code> means liquidity insufficient, <code>false</code> means liquidity enough.</td></tr><tr><td><strong>deviationRatio</strong></td><td>Number</td><td><mark style="color:red;">Price deviation ratio, (0.01 means 1%),  indicating the degree of difference between the aggregator result and market price. When the price deviation ratio is undefined (no reference market price available) or relatively large (significant deviation from existing market prices), provide users with a reference option on whether to execute the trade at the current price to avoid potential asset losses.</mark></td></tr><tr><td><strong>packages</strong></td><td>Map&#x3C;string, string></td><td>When user pass new version parameters, it will return  newest aggregator packages data.</td></tr><tr><td><strong>overlayFee</strong></td><td>Number</td><td>The amount for overlay fee.</td></tr><tr><td><strong>totalDeepFee</strong></td><td>Number</td><td>Calculated need deep fee for deep pools.</td></tr><tr><td><strong>error</strong></td><td>RouterError</td><td>Error code and msg for aggregator.</td></tr></tbody></table>

### Example

```typescript
import { AggregatorClient, getAllProviders } from "@cetusprotocol/aggregator-sdk"
import BN from "bn.js"

const client = new AggregatorClient({})

const amount = new BN(1000000)
const from = "0x2::sui::SUI"
const target = "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS"
const providers = getAllProviders()

const router = await client.findRouters({
  from,
  target,
  amount,
  byAmountIn: true, // `true` means fix input amount, `false` means fix output amount
  providers
})
```

## 2. Build fast swap transaction

This method will send swaped coins to user directly. Here are three type fast swap params:&#x20;

* **`BuildFastRouterSwapParamsV3`**: The new SDK version only supports this parameter format. (Only support in aggregator v3 version, version ≥ v1.0.0)
* `BuildFastRouterSwapParamsV2`: **This legacy parameter is no longer supported in the latest SDK versions (v >= 1.0.0).**. (Only support in aggregator v2 version, v1.0.0> version >= v0.0.0)
* `BuildFastRouterSwapParams`: Here's the English translation: **This legacy parameter is no longer supported in the latest SDK versions (v >= 1.0.0).**(Only support in aggregator v2 version, v1.0.0> version >= v0.0.0)

{% hint style="success" %}
We recommend **using the V3** version of the parameters if you upgrade to the latest SDK versions (version > v1.1.1). This way, if a contract on any platform undergoes a breaking update in the future, you won't need to make any changes; the SDK will automatically update to the latest contract address through the response returned by find router methods, while also reducing gas costs by leveraging the most optimized contract versions
{% endhint %}

### BuildFastRouterSwapParamsV3

**Required** **Params**

<table><thead><tr><th width="146">Name</th><th width="221.21875">Type</th><th>Details</th></tr></thead><tbody><tr><td><strong>router</strong></td><td>RouterDataV3 Object</td><td>returned by find router method in latest aggregator sdk version</td></tr><tr><td><strong>slippage</strong></td><td>Number</td><td>A value between 0 and 1, representing the maximum allowed price slippage as a percentage. A value of 0.01 allows up to 1% price slippage. This parameter is crucial for protecting your assets in a rapidly changing market.</td></tr><tr><td><strong>txb</strong></td><td>Transaction</td><td>The programmable transaction builder.</td></tr></tbody></table>

#### Optional parameters

<table><thead><tr><th width="204">Name</th><th width="121">Type</th><th width="422">Details</th></tr></thead><tbody><tr><td><strong>partner</strong></td><td>String</td><td>The partner address. <a href="../../via-sdk/features-available/partner-swap#partner">Details about partner can be found here.</a><br>You can now set the partner directly during client initialization. This parameter will soon be deprecated; please migrate your configuration.</td></tr><tr><td><strong>refreshAllCoins</strong></td><td>Boolean</td><td> If true, retrieves all coin types when setting up the swap; if false, uses the existing coins.</td></tr><tr><td><strong>payDeepFeeAmount</strong></td><td>Number</td><td>The deep amount for pay deep fee in deepbookv3 path. Currently, all pools that charge a swap fee are covered by Cetus.</td></tr></tbody></table>

### Example

<pre class="language-typescript"><code class="lang-typescript">import { AggregatorClient } from "@cetusprotocol/aggregator-sdk"
import { Transaction } from '@mysten/sui/transactions';
<strong>
</strong>const client = new AggregatorClient({})
<strong>
</strong><strong>const amount = new BN(1000000)
</strong>const from = "0x2::sui::SUI"
const target = "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS"

const router = await client.findRouters({
  from,
  target,
  amount,
  byAmountIn: true, // `true` means fix input amount, `false` means fix output amount
})

const txb = new Transaction()

await client.fastRouterSwap({
  router,
  txb,
  slippage: 0.01,
})
</code></pre>

## 3. Build swap transaction and return target coin object(use the whole input coin)

This method will completely consume the input coin amount and return coin objects, used to build ptb.&#x20;

* **`BuildRouterSwapParamsV3`**: The new parameter types is more clear and can support dynamic update latest package by aggregator.&#x20;
* **`BuildRouterSwapParamsV2`**: The new parameter types is more clear and can support dynamic update latest package by aggregator.&#x20;
* **`BuildRouterSwapParams`**: The old parameter types will continue to be supported.

### **BuildRouterSwapParamsV3**

**Required** **Params**

<table><thead><tr><th width="146">Name</th><th width="176">Type</th><th>Details</th></tr></thead><tbody><tr><td><strong>routers</strong></td><td>RouterData Object</td><td>Returned by find router method</td></tr><tr><td><strong>inputCoin</strong></td><td>TransactionObjectArgument</td><td>The input coin object to be swapped. <mark style="color:red;"><strong>Important</strong></mark><strong>:</strong> This method will completely consume the input coin amount. If you need to set a maximum limit on how much of the input coin can be used (for example, to implement slippage protection on the input side), you should use <code>routerSwapWithMaxAmountIn</code> method.</td></tr><tr><td><strong>slippage</strong></td><td>Number</td><td>A value between 0 and 1, representing the maximum allowed price slippage as a percentage. A value of 0.01 allows up to 1% price slippage. This parameter is crucial for protecting your assets in a rapidly changing market.</td></tr><tr><td><strong>txb</strong></td><td>Transaction</td><td>The programmable transaction builder.</td></tr></tbody></table>

#### Optional parameters

<table><thead><tr><th width="211">Name</th><th width="125">Type</th><th width="422">Details</th></tr></thead><tbody><tr><td><strong>partner</strong></td><td>String</td><td>The partner address. <a href="../../via-sdk/features-available/partner-swap#partner">Details about partner can be found here.</a><br>You can now set the partner directly during client initialization. This parameter will soon be deprecated; please migrate your configuration.</td></tr><tr><td><strong>refreshAllCoins</strong></td><td>Boolean</td><td> If true, retrieves all coin types when setting up the swap; if false, uses the existing coins.</td></tr><tr><td><strong>deepbookv3DeepFee</strong></td><td>TransactionObjectArgument</td><td>The deep fee obejct argument for pay deep fee in deepbookv3 path. Currently, all pools that charge a swap fee are covered by Cetus.</td></tr></tbody></table>

### Example

```typescript
import { AggregatorClient } from "@cetusprotocol/aggregator-sdk"
import { Transaction } from '@mysten/sui/transactions';

const client = new AggregatorClient({})

const amount = new BN(1000000)
const from = "0x2::sui::SUI"
const target = "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS"

const router = await client.findRouters({
  from,
  target,
  amount,
  byAmountIn: true, // `true` means fix input amount, `false` means fix output amount
})

const txb = new Transaction()

const targetCoin = await client.routerSwap({
  router,
  txb,
  inputCoin, // the whole coin will be used in the swap.
  slippage: 0.01,
})

// you can use this target coin object argument to build your ptb.
client.transferOrDestoryCoin(
    txb,
    targetCoin,
    target
)
```

## 4. Build swap transaction and return target coin object (with maximum input protection)

This method builds a swap transaction with **maximum input amount validation**. It returns the target coin object and can be used to build PTB (Programmable Transaction Blocks).

#### When to use `routerSwapWithMaxAmountIn`

Use this method when you need to:

* **Protect against excessive input usage** - Ensure the swap doesn't consume more than expected
* **Implement input-side slippage protection** - Set a hard cap on how much input can be used
* **Handle dynamic coin balances** - When you're not certain of the exact coin balance being provided
* **Build complex PTB logic** - Where you need precise control over maximum input consumption

#### Comparison: `routerSwap` vs `routerSwapWithMaxAmountIn`

| Feature               | `routerSwap`                      | `routerSwapWithMaxAmountIn`           |
| --------------------- | --------------------------------- | ------------------------------------- |
| **Input Coin Usage**  | **Consumes ENTIRE inputCoin**     | **May use LESS than inputCoin**       |
| **Validation**        | No maximum limit                  | Validates against `maxAmountIn`       |
| **On-chain Behavior** | Uses all provided coins           | Aborts if amount exceeds limit        |
| **Use Case**          | Standard swaps with known amounts | Swaps with dynamic/uncertain balances |
| **Return Value**      | Target coin object                | Target coin object                    |

⚠️ **Critical Difference: inputCoin Behavior**

**`routerSwap` - Full Consumption**

```typescript
// This method will consume the ENTIRE inputCoin provided
// The whole coin will be used in the swap - there is NO partial usage
const targetCoin = await client.routerSwap({
  router: routers,
  txb,
  inputCoin,  // ⚠️ This ENTIRE coin will be consumed
  slippage: 0.01,
})
```

**Important:** If you provide a coin with 1000 SUI, the **entire 1000 SUI** will be used in the swap, regardless of the router's `amountIn`. This method does not support partial coin usage.

**`routerSwapWithMaxAmountIn` - Protected Consumption**

```typescript
// This method validates the amount and can work with dynamic balances
const targetCoin = await client.routerSwapWithMaxAmountIn({
  router: routers,
  txb,
  inputCoin,  // ✅ Only the required amount will be used
  slippage: 0.01,
  maxAmountIn: new BN(2000000), // Hard limit: max 2 SUI
})
```

**Important:** This method adds on-chain validation to ensure the swap does not exceed `maxAmountIn`. The transaction will **abort** if the required amount exceeds this limit, protecting your assets from unexpected large swaps.

***

### BuildRouterSwapParamsV3 (with maxAmountIn)

Extension of `BuildRouterSwapParamsV3` with additional maximum amount validation.

#### Required Params

<table><thead><tr><th width="134.01953125">Name</th><th width="163.5546875">Type</th><th>Details</th></tr></thead><tbody><tr><td><strong>router</strong></td><td>RouterDataV3 Object</td><td>Returned by <code>findRouters</code> method. Must include the <code>packages</code> field with aggregator v3 package address.</td></tr><tr><td><strong>inputCoin</strong></td><td>TransactionObjectArgument</td><td>The input coin object to be swapped.<mark style="color:red;"><strong>Important</strong></mark><strong>:</strong> Unlike <code>routerSwap</code>, this methods comes with a maxAmountIn input and the final executed amount won't exceed this cap</td></tr><tr><td><strong>slippage</strong></td><td>Number</td><td>A value between 0 and 1, representing the maximum allowed price slippage as a percentage. A value of 0.01 allows up to 1% price slippage. This parameter protects your assets from unfavorable price movements during swap execution.</td></tr><tr><td><strong>txb</strong></td><td>Transaction</td><td>The programmable transaction builder.</td></tr><tr><td><strong>maxAmountIn</strong></td><td>BN | string | number| bigint</td><td><strong>Maximum input amount allowed for this swap.</strong> The transaction will abort on-chain if the swap requires more than this amount. This provides an additional layer of protection against unexpected large swaps or slippage on the input side.</td></tr></tbody></table>

&#x20;Optional Parameters

<table><thead><tr><th width="189.93359375">Name</th><th width="165.546875">Type</th><th>Details</th></tr></thead><tbody><tr><td><strong>partner</strong></td><td>String</td><td>The partner address. <a href="../../via-sdk-v2/sdk-modules/cetusprotocol-sui-clmm-sdk/partner-swap#partner">Details about partner can be found here.</a>You can now set the partner directly during client initialization. This parameter will soon be deprecated; please migrate your configuration.</td></tr><tr><td><strong>deepbookv3DeepFee</strong></td><td>TransactionObjectArgument</td><td>The DEEP token object for paying fees in DeepBook V3 pools. Currently, all pools that charge a swap fee are covered by Cetus, so you typically don't need to provide this.</td></tr><tr><td><strong>fixable</strong></td><td>Boolean</td><td>Advanced parameter for fixable router swap. Used in special swap scenarios. Default: <code>false</code></td></tr></tbody></table>

**Key Feature:** This method validates that the input coin amount does not exceed the specified `maxAmountIn`. The transaction will **abort on-chain** if the validation fails.

### Code Examples

```typescript
import { AggregatorClient } from "@cetusprotocol/aggregator-sdk"
import { Transaction } from "@mysten/sui/transactions"
import BN from "bn.js"

const client = new AggregatorClient({})
const txb = new Transaction()

// Find the best route
const routers = await client.findRouters({
  from: "0x2::sui::SUI",
  target: "0x06864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS",
  amount: new BN(1000000), // 1 SUI
  byAmountIn: true,
})

// Your input coin (could be from wallet or created in PTB)
const inputCoin = txb.object("0x...")

// Execute swap with maximum amount protection
const targetCoin = await client.routerSwapWithMaxAmountIn({
  router: routers,
  txb,
  inputCoin,
  slippage: 0.01, // 1% slippage
  maxAmountIn: new BN(1500000), // Maximum 1.5 SUI allowed
})

// If the swap requires more than 1.5 SUI, the transaction will ABORT
// Use the target coin in your PTB
txb.transferObjects([targetCoin], yourAddress)
```

## 5. FAQ&#x20;

### 5.1. Why use v3 swap params?

#### 1. **Automatically merges duplicate paths**

By combining the latest path merging and sorting algorithms, duplicate pools are consolidated, resulting in significant gas savings when dealing with multiple split paths.

#### 2. Support dynamic use latest package version

The new parameters will pass the entire result from find router, which includes the latest contract address. However, this feature is only effective in SDK versions greater than 0.3.18.

In the future, we will continue to support the old version of swap parameters in both swap methods. However, upgrading to the new version will allow you to avoid mandatory SDK version updates.

#### 3. Remove duplicate parameter byAmountIn

Now, the find router result will return the value based on the amount in, allowing you to directly obtain it from the find router result in the new swap parameters.

### 5.2. How to Migrate to Aggregator V3？

**No code changes needed for basic usage:**

* Use the latest sdk version. (version >= v1.1.1)
* Client initialization stays the same
* `findRouter` now returns V3 structure automatically
* `fastRouterSwap` and `routerSwap` accept the new format transparently
* Update display logic only if showing detailed `RouterDataV3` to users

### 5.3. How to set providers?

1. You can ignore the providers parameters; the aggregator server will automatically set all usable providers based on the SDK version.
2. You can use the `getAllProviders()` method to retrieve all providers. Additionally, you can use the `getProvidersIncluding()` and `getProvidersExcluding()` methods to filter out specific providers or select only certain ones from the complete list.

```typescript
import { getAllProviders, getProvidersExcluding } from "@cetusprotocol/aggregator-sdk"
const allProviders = getAllProviders()
console.log(allProviders)
[
      'CETUS',         'KRIYA',
      ...
      'MOMENTUM',      'STEAMM_OMM',
      'STEAMM_OMM_V2'
]
    
const providersExcept = getProvidersExcluding(["CETUS"])
console.log(providersExcept)
[
      'KRIYA',      'FLOWX',
      ...
      'STEAMM_OMM', 'STEAMM_OMM_V2'
]

```

3. While you can manually specify the providers you want to use, as the number of providers increases, manual configuration may lead to the omission of some providers, which could affect your price advantage."

### 5.4. How to fix error "All Pyth price nodes are unavailable. Cannot fetch price data. Please switch to or add new available Pyth nodes. Detailed error: aborted"？

**Reason**: Some providers, such as Headalpmm and Metastable, rely on Pyth oracle prices when building transactions. Currently, we have a default configuration that connects to Pyth's publicly available node. However, if you frequently build transactions, you may encounter limitations with the Pyth public nodes(<https://hermes.pyth.network>).

**Solutions**: We recommend setting up a private Pyth node interface as an additional backup. This will ensure uninterrupted access to HaedalHMM and Metastable, even if the public node experiences occasional downtime.

```typescript
const client = new AggregatorClient({
  // endpoint, // If you do not have a exclusive aggregator api domain，just use cetus default aggregator endpoints.
  signer: wallet,
  client: suiClient,
  env: Env.Mainnet,
  pythUrls?: ["YOUR_PYTH_URL", "ANOTHER_PYTH_URL"], // Optional. Custom Pyth price feed URLs. Defaults to null (uses built-in endpoints).
  partner?: "YOUR_CETUS_CLMM_PARTNER_ID", // Optional. Partner ID for CLMM fee sharing. Set once during initialization instead of per swap. Defaults to null (no fee sharing).
  cetusDlmmPartner?: "YOUR_CETUS_DLMM_PARTNER_ID", // Optional. Partner ID for DLMM fee sharing. Defaults to null (no fee sharing).
  overlayFeeRate?: 0.01, // Optional. Overlay fee rate (0.01 represents 1%). Defaults to 0 (no overlay fee).
  overlayFeeReceiver?: "0x..", // Optional. Address to receive the overlay fees. Defaults to null. Required if overlayFeeRate is set.
})
```

&#x20;Another way, you can opt not to use Headalpmm and Metastable, but this will require you to manually configure the provider when find router.&#x20;

```typescript
const router = await client.findRouters({
  from,
  target,
  amount,
  byAmountIn: true,
  providers: ["CETUS","SCALLOP","AFTERMATH","FLOWXV3","AFSUI","STEAMM","VOLO","KRIYAV3","KRIYA","ALPHAFI","FLOWX","BLUEMOVE","DEEPBOOKV3","BLUEFIN","HAEDAL","TURBOS","SPRINGSUI","STEAMM","METASTABLE","HAWAL","OBRIC"]
})
```
