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

@bidask-protocol/sdk

v0.9.2

Published

Bidask Protocol SDK

Readme

Bidask SDK

Warning: This library is in beta. It may contain bugs and is subject to breaking changes in future updates

Code examples

You can always find code examples in the examples directory.

Providing Liquidity

Usage Example

import { Address } from "@ton/ton";
import { TonConnectUI } from "@tonconnect/ui-react";
import {
  PoolContract,
  RangeContract,
  JettonMaster,
  createProvideNativeLiquidityTxParams,
  createProvideLiquidityTxParams,
  getBinByPrice,
  getPriceFromSqrtPriceX128,
  toBigInt,
  isZeroAddress,
  getDeadline,
  createCurveShape,
  TxParams,
} from "@bidask-protocol/sdk";

// The pool you want to provide liquidity to
const selectedPool = {
  poolAddress: "0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d",
  bps: 60n,
  token0: {
    address: "0:fa0b96ec813ecc248d6505570d99311c6936a565507196bc759014e24aaaca84";
    decimals: "9";
  },
  token1: {
    address: "0:0000000000000000000000000000000000000000000000000000000000000000";
    decimals: "9";
  };

// The amount of tokens you want to provide liquidity
const token0Amount = "100"; // human readable format
const token1Amount = "230"; // human readable format

// Create pool contract instance
const pool = PoolContract.create(Address.parse(selectedPool.poolAddress));
const poolContract = tonapiClientAdapter.open(pool);

// Get the active range to determine current price
const activeRangeAddress = await poolContract.getActiveRange();
const activeRangeContract = tonapiClientAdapter.open(
  RangeContract.create(activeRangeAddress)
);

// Get current price information
const currentSqrtPrice = await activeRangeContract.getSqrtPrice();
const currentPrice = getPriceFromSqrtPriceX128(currentSqrtPrice);
const currentBinIndex = getBinByPrice(currentPrice, selectedPool.bps);

// Providing liquidity to 10 bins on each side of the current price
const firstBinIndex = currentBinIndex - 10;
const lastBinIndex = currentBinIndex + 10;

const token0AmountBN = toBigInt(token0Amount, selectedPool.token0.decimals);
const token1AmountBN = toBigInt(token1Amount, selectedPool.token1.decimals);

// Create the shape of the bins to provide
// Available options are: createCurveShape, createSpotShape, createBidaskShape
const binsToProvide = createCurveShape({
  token0Amount: token0AmountBN,
  token1Amount: token1AmountBN,
  currentPrice: currentPrice,
  fromBin: firstBinIndex,
  toBin: lastBinIndex,
  bps: binStep,
})

// Get token wallet addresses
const jetton0 = await JettonMaster.create(
  Address.parse(selectedPool.token0.address)
);
const jetton0Contract = tonapiClientAdapter.open(jetton0);
const jetton0Wallet = await jetton0Contract.getWalletAddress(
  Address.parse(userAddress)
);

// Get initialized ranges
const rangesStatuses = await poolContract.getRangesStatusesByLiquidityBins(binsToProvide);

const initializedRanges = Object.entries(rangesStatuses)
  .filter(([, status]) => status === RangeStatus.Initialized)
  .map(([range]) => Number(range));

let txParams
// Handle TON + Jetton case
if (isZeroAddress(selectedPool.token1.address)) {
  // Create transaction parameters for providing TON + Jetton
  txParams = createProvideNativeLiquidityTxParams({
    poolAddress: pool.address,
    senderAddress: Address.parse(userAddress),
    binsToProvide: binsToProvide,
    jettonWalletAddress: jetton0Wallet,
    initializedRanges: initializedRanges,
  });
} else {
  // Handle Jetton + Jetton case
  const jetton1 = await JettonMaster.create(
    Address.parse(selectedPool.token1.address)
  );
  const jetton1Contract = tonapiClientAdapter.open(jetton1);
  const jetton1Wallet = await jetton1Contract.getWalletAddress(
    Address.parse(userAddress)
  );

  // Create transaction parameters for providing two jettons
  txParams = createProvideLiquidityTxParams({
    poolAddress: pool.address,
    jettonWalletAddress0: jetton0Wallet,
    jettonWalletAddress1: jetton1Wallet,
    senderAddress: Address.parse(userAddress),
    binsToProvide: binsToProvide,
    initializedRanges: initializedRanges,
  });
}

// Send transactions
tonConnectUI.sendTransaction({
  validUntil: getDeadline(),
  messages: txParams.map((tx) => ({
    address: tx.to.toString(),
    amount: tx.value.toString(),
    payload: tx.payload.toBoc().toString("base64"),
  })),
});

Burning Liquidity

Usage Example

import { Address } from "@ton/ton";
import { TonConnectUI } from "@tonconnect/ui-react";
import {
  PoolContract,
  RangeContract,
  LpMultitokenContract,
  createBurnAllTxParams,
  createBurnTxParams,
  getDeadline,
  TxParams,
} from "@bidask/sdk";

// The pool you want to burn liquidity from
const selectedPool = {
  poolAddress:
    "0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d",
  bps: 60n,
  token0: {
    address: "0:fa0b96ec813ecc248d6505570d99311c6936a565507196bc759014e24aaaca84";
    decimals: "9";
  },
  token1: {
    address: "0:0000000000000000000000000000000000000000000000000000000000000000";
    decimals: "9";
  };

// The percentage of liquidity to burn
const burnPercentage = 50;

// Create pool contract instance
const pool = PoolContract.create(Address.parse(selectedPool.poolAddress));
const poolContract = tonapiClientAdapter.open(pool);

// Get the active range
const activeRangeAddress = await poolContract.getActiveRange();
const activeRangeContract = tonapiClientAdapter.open(
  RangeContract.create(activeRangeAddress)
);

// Get LP multitoken wallet address
const lpMultitokenAddress = await activeRangeContract.getLpMultitokenWallet(
  Address.parse(tonConnectUI.account!.address)
);

let txParams: TxParams;
// Burn all liquidity
if (burnPercentage === 100) {
  txParams = createBurnAllTxParams({ lpMultitokenAddress });
} else {
  // Burn partial liquidity
  const lpMultitokenContract = tonapiClientAdapter.open(
    LpMultitokenContract.create(lpMultitokenAddress)
  );

  const lpTokenBins = await lpMultitokenContract.getTokens();

  txParams = createBurnTxParams({
    lpMultitokenAddress,
    binsToBurn: Object.fromEntries(
      Object.entries(lpTokenBins).map(([bin, amount]) => {
        return [Number(bin), (amount * BigInt(burnPercentage)) / 100n];
      })
    ),
  });
}

tonConnectUI.sendTransaction({
  validUntil: getDeadline(),
  messages: [
    {
      address: burnTxParams.to.toRawString(),
      amount: burnTxParams.value.toString(),
      payload: burnTxParams.payload.toBoc().toString("base64"),
    },
  ],
});

Swapping Tokens

Usage Example

import {
  createJettonSwapTxParams,
  createTonSwapTxParams,
  getDeadline,
  getPriceFromSqrtPriceX128,
  getSqrtPriceX128,
  isZeroAddress,
  JettonMaster,
  JettonWalletContract,
  PoolContract,
  RangeContract,
  SwapPartialExecutionParams,
  toBigInt,
  TxParams,
} from '@bidask/sdk'
import { Address } from '@ton/ton'
import { TonConnectUI } from '@tonconnect/ui-react'

// The pool you want to swap in
const poolData = {
  poolAddress: '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d',
  bps: 60n,
  token0: {
    address: '0:fa0b96ec813ecc248d6505570d99311c6936a565507196bc759014e24aaaca84',
    decimals: '9',
  },
  token1: {
    address: '0:0000000000000000000000000000000000000000000000000000000000000000',
    decimals: '9',
  },
}

// Token you're swapping from
const tokenFrom = poolData.token0

// Token you're swapping to
const tokenTo = poolData.token1

// Amount to swap
const amountFromRaw = '100' // human readable format
const slippage = 0.01 // 1% slippage

// Create pool contract instance
const pool = PoolContract.create(Address.parse(poolData.poolAddress))
const poolContract = tonapiClientAdapter.open(pool)

// Get current price
const activeRangeAddress = await poolContract.getActiveRange()
const activeRange = RangeContract.create(activeRangeAddress)
const activeRangeContract = tonapiClientAdapter.open(activeRange)
const sqrtPriceX128 = await activeRangeContract.getSqrtPrice()
const currentPrice = getPriceFromSqrtPriceX128(sqrtPriceX128)

// Partial execution parameters
let partialExecutionParams: SwapPartialExecutionParams
if (partialExecution) {
  const isToken0Swap = Address.parse(tokenFrom.address).equals(jettonMaster)

  // MINIMUM/MAXIMUM price you're willing to swap at in case of partial execution
  const lastPrice = isToken0Swap ? currentPrice * (1 - slippage) : currentPrice * (1 + slippage)

  partialExecutionParams = {
    allowPartial: true,
    sqrtX128LastPrice: getSqrtPriceX128(lastPrice),
  }
} else {
  // MINIMUM amount out you expect to receive
  const minimumExpectedAmountOut = toBigInt('232', tokenTo.decimals)

  partialExecutionParams = {
    allowPartial: false,
    minAmountToReceive: minimumExpectedAmountOut,
  }
}

let txParams: TxParams
if (isZeroAddress(Address.parse(tokenFrom.address))) {
  // Handle TON swap -> Jetton case
  const lastPrice = currentPrice * (1 + slippage)

  txParams = createTonSwapTxParams({
    poolAddress: pool.address,
    amountIn: toBigInt(amountFromRaw, 9),
    senderAddress: Address.parse(userAddress),
    receiverAddress: Address.parse(userAddress),
    ...partialExecutionParams,
  })
} else {
  // Handle Jetton swap -> Jetton/TON case
  const tokenFromJettonContract = tonapiClientAdapter.open(
    JettonMaster.create(Address.parse(tokenFrom.address)),
  )

  const tokenFromUserWallet = await tokenFromJettonContract.getWalletAddress(
    Address.parse(walletAddress),
  )

  txParams = createJettonSwapTxParams({
    poolAddress: pool.address,
    amountIn: toBigInt(amountFromRaw, tokenFrom.decimals),
    tokenIn: tokenFromJettonContract.address,
    senderAddress: Address.parse(userAddress),
    receiverAddress: Address.parse(userAddress),
    senderAddress: Address.parse(userAddress),
    jettonWalletAddress: tokenFromUserWallet,
    ...partialExecutionParams,
  })
}

tonConnectUI.sendTransaction({
  validUntil: getDeadline(),
  messages: [
    {
      address: txParams.to.toRawString(),
      amount: swapParams.value.toString(),
      payload: txParams.payload.toBoc().toString('base64'),
    },
  ],
})

Trading Account

Deposit into trading account

import { createTradeAccountDepositTxParams } from '@bidask/sdk'
import { Address } from '@ton/ton'
import { TonConnectUI } from '@tonconnect/ui-react'

const poolAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'
const userToken0WalletAddress = '0:fa0b96ec813ecc248d6505570d99311c6936a565507196bc759014e24aaaca84'
const userToken1WalletAddress = '0:0000000000000000000000000000000000000000000000000000000000000000' // Zero address for TON
const token0Amount = '100' // human readable format
const token0Decimals = 9
const token1Amount = '230' // human readable format
const token1Decimals = 9
const userAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'

const tradeAccountPublicKey = 'public_key'
const tradeAccountSeed = 0

const transactions = createTradeAccountDepositTxParams({
  poolAddress: Address.parse(poolAddress),
  token0UserWalletAddress: Address.parse(userToken0WalletAddress),
  token1UserWalletAddress: Address.parse(userToken1WalletAddress),
  token0Amount: toBigInt(token0Amount, token0Decimals),
  token1Amount: toBigInt(token1Amount, token1Decimals),
  userAddress: Address.parse(userAddress),
  senderAddress: Address.parse(userAddress),
  publicKey: tradeAccountPublicKey,
  seed: tradeAccountSeed,
})

const transaction = {
  validUntil: Math.floor(Date.now() / 1000) + 60,
  messages: transactions.map((tx) => ({
    address: tx.to.toRawString(),
    amount: String(tx.value),
    payload: tx.payload.toBoc().toString('base64'),
  })),
}

tonConnectUI.sendTransaction(transaction)

Swap tokens using trading account

import { getDeadline, TradeAccount } from '@bidask/sdk'
import { KeyPair } from '@ton/crypto'
import { Address } from '@ton/ton'
import { TonConnectUI } from '@tonconnect/ui-react'

const tradingAccountAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'
const tradingAccount = TradeAccount.createFromAddress(Address.parse(tradingAccountAddress))
const tradingAccountContract = tonapiClientAdapter.open(tradingAccount)

const poolAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'
const isX = true // if swapping token0(X) to token1(Y)
const tokenFromAmount = '100' // human readable format
const tokenFromDecimals = 9
const userAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'

const tradeAccountKeypair: KeyPair = {}
const tradeAccountSeed = 0

const seedCell = beginCell().storeUint(tradeAccountSeed, 64).endCell()

const tradeAccountSeqno = await tradingAccountContract.getSeqno()

// check `Swapping tokens` block for partial execution params logic
let partialExecutionParams: SwapPartialExecutionParams
// {...}

tradingAccountContract.sendExternalSwap(
  tradeAccountKeypair,
  getDeadline(),
  tradeAccountSeqno,
  Address.parse(poolAddress),
  seedCell,
  {
    receiverAddress: Address.parse(tradingAccountAddress),
    isReceiverAccount: true,
    tokenAmount: toBigInt(tokenFromAmount, tokenFromDecimals),
    isX: isX,
    ...partialExecutionParams,
  },
)

Withdraw tokens from trading account

import { getDeadline, TradeAccount } from '@bidask/sdk'
import { KeyPair } from '@ton/crypto'
import { Address } from '@ton/ton'
import { TonConnectUI } from '@tonconnect/ui-react'

const tradingAccountAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'
const tradingAccount = TradeAccount.createFromAddress(Address.parse(tradingAccountAddress))
const tradingAccountContract = tonapiClientAdapter.open(tradingAccount)

const poolAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'
const token0Amount = '100' // human readable format
const token0Decimals = 9
const token1Amount = '230' // human readable format
const token1Decimals = 9
const userAddress = '0:85e73c7cf6b6434d4ee3f2f2f7e45ed0d594f5a1d71614e674599ce31abc330d'

const tradeAccountKeypair: KeyPair = {}
const tradeAccountSeed = 0

const seedCell = beginCell().storeUint(tradeAccountSeed, 64).endCell()

const tradeAccountSeqno = await tradingAccountContract.getSeqno()

tradingAccountContract.sendExternalWithdraw(
  tradeAccountKeypair,
  getDeadline(),
  tradeAccountSeqno,
  Address.parse(poolAddress),
  seedCell,
  {
    receiverAddress: Address.parse(userAddress),
    token0Amount: toBigInt(token0Amount, token0Decimals),
    token1Amount: toBigInt(token1Amount, token1Decimals),
  },
)