Smart router v2

Swap in the best router v2

In the smart router v2, we mainly started supporting the split computation of optimal routes. To ensure that our functionality is stable, we also have a well-designed fallback scheme in place. If our backend HPC service terminates unexpectedly, we will restart the first version of the sdk for precomputation.

As with the original router, you need to build the router group ahead of time to ensure that fallback scenarios are always available

There are two method to get all pools:

  1. (Stable) If you get all pools by sdk, like ask.Pool.getPools(), you can't get coin decimals, so you need to set coin decimal by youself.

  2. (Speedy) Get pool list from our API. The coin decimals are provided.

NetworkLink

Testnet

Mainnet

https://api-sui.cetus.zone/v2/sui/pools_info

In the latest version, we recommand you to build transaction by TransactionUtil.buildAggregatorSwapTransaction.

All used type in /src/modules/routerModule.ts.

If you want to use SDK to get pool list, you can see the method in router v1 doc.

Pre-calculating

Function input param

Please refer to the original function for specific parameter types.

  • from: coin type of from coin.

  • to: coin type of to coin.

  • amount: amount of from coin.

  • byAmountIn: true means fixed the amount of input, false means fixed the amount of output.

  • amount: the amount of input (byAmountIn = true) or output (byAmountIn = false).

  • priceSplitPoint: split point of price, it control the range of coin losses you may incur.

  • partner: Partner object id.

  • swapWithMultiPoolParams: This is an option about the coin pair what you want to do swap, this is to prevent potential pre-calculation errors in the SDK. In such cases, if there are direct trading pools available, the routing will undergo a downgrade process.

  • orderSplit: Is the order splitting calculation feature enabled.

  • externalRouter: Is integrate external swap pool, now just support deepbook.

Notice: Now, in smart router, if you open enable options: orderSplit or externalRouter, it can't support Partner.

In this example, if you want to use partner function, orderSplit and externalRouter must set false.

async getBestRouter(
  from: string,
  to: string,
  amount: number,
  byAmountIn: boolean,
  priceSplitPoint: number,
  partner: string,
  senderAddress: string,
  swapWithMultiPoolParams?: PreSwapWithMultiPoolParams,
  orderSplit = false,
  externalRouter = false
) { result: AggregatorResult, version: 'v1' | 'v2'}

Build router v2 swap transaction

use TransactionUtil.buildAggregatorSwapTransaction method.

Function input param

Please refer to the original function for specific parameter types.

  • sdk: The sdk include all import config.

  • params: aggregator result in getBestRouter.

  • allCoinAsset: user's all coin object id.

  • partner: partner object id. If don't create partner, just set empty string("").

  • priceSlippagePoint: Slippage point of price, it control the range of coin losses you may incur.

  • recipient: (Option) the address about all coins recipient. If recipient not set, transfer objects move call will use sender get by ctx.

Please update the SDK to the latest version 3.17.3+ , and no longer use the SDK's default senderAddress as the recipient for transferObjects.

Example

Get all pools by centralization API. If you want to get all pools by SDK, you can see router tutorial.

Ps: In this example, i will swap 1k SUI to USDC.

import BN from 'bn.js'


const coinMap = new Map()
const poolMap = new Map()

const resp: any = await fetch('https://api-sui.cetus.zone/v2/sui/pools_info', { method: 'GET' })
const poolsInfo = await resp.json()

if (poolsInfo.code === 200) {
  for (const pool of poolsInfo.data.lp_list) {
    if (pool.is_closed) {
      continue
    }

    let coin_a = pool.coin_a.address
    let coin_b = pool.coin_b.address

    coinMap.set(coin_a, {
      address: pool.coin_a.address,
      decimals: pool.coin_a.decimals,
    })
    coinMap.set(coin_b, {
      address: pool.coin_b.address,
      decimals: pool.coin_b.decimals,
    })

    const pair = `${coin_a}-${coin_b}`
    const pathProvider = poolMap.get(pair)
    if (pathProvider) {
      pathProvider.addressMap.set(Number(pool.fee) * 100, pool.address)
    } else {
      poolMap.set(pair, {
        base: coin_a,
        quote: coin_b,
        addressMap: new Map([[Number(pool.fee) * 100, pool.address]]),
      })
    }
  }
}

const coins: CoinProvider = {
  coins: Array.from(coinMap.values()),
}
const paths: PathProvider = {
  paths: Array.from(poolMap.values()),
}

sdk.Router.loadGraph(coins, paths)


// The first two addresses requiring coin types.
const fromCoin = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI"
const toCoin = "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN"
const amount = new BN('1000000000000')
const byAmountIn = false
const priceSplitPoint = 0.5
const partner = ''

const res = (await sdk.RouterV2.getBestRouter(fromCoin, toCoin, amount, byAmountIn, priceSplitPoint, partner, undefined, true, false))
            .result as AggregatorResult

// If find the best swap router, then send transaction.
if (!result?.isExceed) {
  const allCoinAsset = await sdk.Resources.getOwnerCoinAssets(sdk.senderAddress)
  // If recipient not set, transfer objects move call will use ctx sender.
  const payload = await TransactionUtil.buildAggregatorSwapTransaction(sdk, res, allCoinAsset, '', 0.5)
  const signer = new RawSigner(sendKeypair, sdk.fullClient)
  const transferTxn = await sendTransaction(signer, payload)
}

Last updated