@bidask-protocol/sdk
TypeScript icon, indicating that this package has built-in type declarations

0.4.7 • Public • Published

Bidask SDK

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

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'),
    },
  ],
})

Readme

Keywords

Package Sidebar

Install

npm i @bidask-protocol/sdk

Weekly Downloads

96

Version

0.4.7

License

MIT

Unpacked Size

606 kB

Total Files

8

Last publish

Collaborators

  • foprta
  • gkopeliovich