npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@renec-foundation/swap-router-sdk

v1.0.4-alpha.0

Published

TypeScript SDK for finding the optimal swap route

Readme

Swap Router SDK

This is a private package, so make sure to login to npm first.

yarn add @renec-foundation/swap-router-sdk

Compute the optimal swap route

import Decimal from 'decimal.js'

import { AnchorProvider } from '@project-serum/anchor'
import { buildWhirlpoolClient, WhirlpoolContext } from '@renec-foundation/nemoswap-sdk'
import { findOptimalRoute, PoolList, SwapOption } from '@renec-foundation/swap-router-sdk'
import { useAnchorWallet } from '@renec-foundation/wallet-adapter-react'
import { Commitment, Connection, PublicKey } from '@solana/web3.js'

const commitment: Commitment = 'confirmed'
const connection = new Connection(RPC_URL, { commitment })
const wallet = useAnchorWallet()
const provider = new AnchorProvider(connection, wallet, { commitment })
const context = WhirlpoolContext.withProvider(provider, new PublicKey(POOL_PROGRAM_ID))
const client = buildWhirlpoolClient(context)

// List of pools to search on. This can be fetched from backend.
declare const poolList: PoolList[]

// Token pair for swapping.
declare const tokenAMintAddress: PublicKey
declare const tokenBMintAddress: PublicKey

// The amount of token for swapping.
// This can be the amount of tokenA or tokenB, depending on the swap option.
declare const tokenAmount: Decimal

// If ExactIn, router will find the route that gives the most tokenB for a given amount of tokenA.
// If ExactOut, router will find the route that needs the least tokenA for a given amount of tokenB.
declare const option: SwapOption

const route = await findOptimalRoute({
  client,
  poolList,
  tokenAMintAddress,
  tokenBMintAddress,
  tokenAmount,
  option,
})

if (route) {
  const txBuilder = await getSwapTxBuilderFromRoute(route)
  await txBuilder.buildAndExecute()
}

Error handling

To get an exception if no route is found, set silent to false.

import { SwapError } from '@renec-foundation/swap-router-sdk'

try {
  const route = await findOptimalRoute({
    client,
    poolList,
    tokenAMintAddress,
    tokenBMintAddress,
    tokenAmount,
    option,
    silent: false,
  })
} catch (err) {
  if (err instanceof SwapError) {
    const { code, message } = err
  }
}

Versioned transaction and lookup table

import { getV0TxFromRoute } from '@renec-foundation/swap-router-sdk'

// Addresses of lookup tables that should be used for this swap.
declare const lookupTableAddresses: PublicKey[]

const v0Tx = await getV0TxFromRoute(client, route, lookupTableAddresses)
await connection.sendTransaction(v0Tx)

Serialize and deserialize

You may want to serialize the route info before sending as JSON.

import { deserializeRoute, serializeRoute } from '@renec-foundation/swap-router-sdk'

// Send route info as JSON.
const serializedRoute = serializeRoute(route)
const data = JSON.stringify(serializedRoute)

// Receive JSON route info and deserialize it.
const parsedData = JSON.parse(data)
const deserializedRoute = await deserializeRoute(client, parsedData)

if (deserializedRoute) {
  const txBuilder = await getSwapTxBuilderFromRoute(deserializedRoute)
  await txBuilder.buildAndExecute()
}

Average price

To calculate the average price of the route, we first weight the accumulated square-root price of all pools in each sub-route by its contribution to the overall route, i.e., splitRate, and then compute the total of all weighted prices.

import {
  computeAccumulatedSqrtPriceOfPoolRoute,
  convertSwapRouteToPoolRoute,
} from '@renec-foundation/swap-router-sdk'

let sqrtPriceOfRoute = new Decimal(0)
route.subRoutes.forEach((subRoute) => {
  const poolRoute = convertSwapRouteToPoolRoute(subRoute.quote.route)
  const sqrtPriceOfPoolRoute = computeAccumulatedSqrtPriceOfPoolRoute(poolRoute)

  // Weight each sqrtPrice by its contribution to the overall route, i.e., splitRate.
  sqrtPriceOfRoute = sqrtPriceOfRoute.add(sqrtPriceOfPoolRoute.price.mul(subRoute.splitRate))
})

// Note that this price is NOT equivalent to the rate
// between the amount of token received over spent.
const actualRateBasedOnQuote = route.estimatedAmountOut.div(route.estimatedAmountIn)
console.log(sqrtPriceOfRoute.eq(actualRateBasedOnQuote)) // false

Swap fee

For each swap instruction (a.k.a. hop) from token A to B, a swap fee, which is a small amount of token A, will be incurred. To calculate the total fee of the entire transaction, we need to accumulate the fee of all hops.

import { getSwapFeeOfHop, SwapFee } from '@renec-foundation/swap-router-sdk'

const fees: SwapFee[] = []
route.subRoutes.forEach((subRoute) => {
  subRoute.quote.route.forEach((hop) => {
    fees.push(getSwapFeeOfHop(hop))
  })
})