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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fullsailfinance/sdk

v8.3.0

Published

SDK for FullSail ve(4,4) dex

Readme

@fullsailfinance/sdk

Overview

TypeScript toolkit for the FullSail ve(4,4) DEX on Sui. It centralizes payload assembly, liquidity management, and token-locking utilities to let applications interact with FullSail mechanics without hand-coding Move transactions.

Installation

npm:
$ npm i @fullsailfinance/sdk
yarn:
$ yarn add @fullsailfinance/sdk

Configuration

import { initFullSailSDK } from '@fullsailfinance/sdk'

const fullSailSDK = initFullSailSDK({
  network: 'mainnet-production',
  // You can also provide your own full node URL and simulation account. It's optional.
  fullNodeUrl: 'https://...',
  simulationAccount: '0x...',
})

After user has connected the wallet, you must set senderAddress to your sdk instance

fullSailSDK.senderAddress = '0x...'
// or
fullSailSDK.setSenderAddress('0x...')

Key Concepts

Gauge

A smart contract that manages staked positions rewards and oSAIL token distribution. Core functions:

  • Position Staking Management: Tracks staked positions, calculates rewards, and enables withdrawal
  • Reward & oSAIL Distribution: Distributes rewards and oSAIL tokens to staked positions. New oSAIL tokens are issued weekly for each epoch
  • Reward Calculation: Calculates earned oSAIL rewards based on staked liquidity and time, and processes reward claims to position owners
  • Fee Collection: Collects and manages fees generated by the associated liquidity pool

Ticks

Discrete price points that define the boundaries of liquidity ranges. Important considerations:

  • Each tick represents a specific price ratio
  • Ticks are spaced at constant intervals determined by the pool's tick spacing

Pool

Initially created without a gauge. It can be added later to enable position staking and voting.

There are two pool entities available through the SDK:

Chain Pool (Pool.getByIdFromChain()): Contains real-time data directly from the blockchain. Data from this entity is always relevant.

Some core/unique properties:

  • currentTickIndex: The tick corresponding to the current price of the pool (determines which liquidity positions are currently active)
  • rewardCoinsInfo: List of reward coins available for this pool
  • currentSqrtPrice: Current sqrt price of the pool

Pool (Pool.getById()): Contains calculated data and metadata from the backend which can be convinient for frontend. It can contain same fields as ChainPool but they may be outdated by a few minutes, especially those that change frequently.

Some core/unique properties:

  • gauge_id: Unique identifier for gauge contract related to this pool
  • gauge_killed: can be true if gauge contract for the pool has been killed. All positions in this pool should be unstaked manually to receive fees.

Use backend pool for stable metadata and gauge_id, use chain pool for relevant current price and reward data.

Position

Represents a range of prices where you provide liquidity to a pool. If gauge exists for this pool, position should be staked, otherwise it will only receive pool rewards. For reward abuse protection new positions always have a 20 minutes cooldown before any rewards can be claimed. You can remove liquidity from a position at any time, but if you do so before cooldown period you will not receive a rewards.

Some core properties:

  • tick_lower: The lower bound of your price range (minimum price where your liquidity is active)
  • tick_upper: The upper bound of your price range (maximum price where your liquidity is active)
  • liquidity: The amount of liquidity provided in this price range
  • stake_info: Information about the position stake object within the gauge. Can be undefined if position not staked or no gauge exists for this pool

Position Rewards

Different position states receive different types of rewards:

  • Position in pool without gauge: Receives pool fees and pool rewards
  • Unstaked position in pool with gauge: Receives only pool rewards
  • Staked position in pool with gauge: Receives oSAIL tokens and pool rewards

oSAIL

oSAIL is the emissions token distributed to staked positions. Each epoch has its own oSAIL token with a specific expiration date - 5 weeks from the start of the epoch. In every method which includes claim rewards rewardChoice field is required to determine which path to take. It can be one of the following values:

  1. "vesail" - lock it into veSAIL to participate in governance and earn trading fees.
  2. "sail" - redeem it for liquid SAIL in a 2 to 1 ratio (100 oSAIL will be redeemed for 50 SAIL).
  3. "usd" - redeem it for USDC in a 50% of the current spot price at time of redemption.

Expired oSAIL can be only locked into veSAIL.

Lock (veSAIL)

Represents voting power and used only for voting. Minted by locking SAIL or oSAIL for a fixed duration. Lock amount multiplied by lock duration determines voting power. isPermanent option commits to the longest available lock period for maximum voting power.

Some core properties:

  • permanent: whether lock is permanent or not
  • voting_power: current voting power provided by this lock. Reduces slowly over time if lock is not permanent
  • is_voting_onchain: whether lock is used for voting at current epoch
  • amount: amount of SAIL locked

Locks are transferable, supports merging, splitting, increasing amount/duration. Liquid SAIL unlocks at lock expiration.

Epoch

7-day cycle during which veSAIL holders vote and predict trading volumes for pools.

Voting

veSAIL holders can vote and predict trading volumes for pools for the next epoch. Only pools with gauge can be voted.

Voters earn from Trading fees from the pools they vote for. Fees are distributed by prediction accuracy and allocated voting power.

Usage examples

If method name ends with ...Transaction, it returns a transaction that should be signed and executed using your sui client or wallet kit. It also accepts transaction as second parameter if you want to add this transaction to existing batch. There are separate methods to create/add liquidity/remove liquidity/close for both kinds of positions (staked and unstaked) if you want to have more control or stronger types.

Positions

Create position

import { ClmmPoolUtil, Percentage, TickMath } from '@fullsailfinance/sdk'

const poolId = '0x0...'

const amountA = 1000000n
const fixedAmountA = true
const roundUp = true
// 1%
const slippage = Percentage.fromNumber(1)

const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)

// get the nearest tick indexes based on current price
const tickLower = TickMath.getPrevInitializableTickIndex(chainPool.currentTickIndex, chainPool.tickSpacing)
const tickUpper = TickMath.getNextInitializableTickIndex(chainPool.currentTickIndex, chainPool.tickSpacing)

// Calculate the opposite coin amount based on the first coin amount and tick range
// This ensures proper liquidity ratio within the specified price range, including slippage
const { maxAmountB } = ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts(
  tickLower,
  tickUpper,
  amountA, // change to amountB if you want to calculate maxAmountA based on amountB
  fixedAmountA, // change to false if you want to calculate maxAmountA based on amountB
  roundUp,
  slippage.toCoefficient(),
  chainPool.currentSqrtPrice,
)

const transaction = await fullSailSDK.Position.openTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  tickLower,
  tickUpper,
  amountA,
  amountB: maxAmountB,
  slippage,
  fixedAmountA,
  currentSqrtPrice: chainPool.currentSqrtPrice,
  // if gaugeId provided, position will be staked automatically.
  gaugeId: pool.gauge_id,
})

Add liquidity to position

Only oSAIL claimed automatically within this transaction. Fees and pool rewards are not.

import { ClmmPoolUtil, MAX_LOCK_DURATION_DAYS, Percentage } from '@fullsailfinance/sdk'

const poolId = '0x0...'
const positionId = '0x0...'
// your existing permanent lock id
const permanentLockId = '0x0...'
// 'vesail' | 'sail' | 'usd'
const rewardChoice = 'vesail'

const amountA = 1000000n
const fixedAmountA = true
const roundUp = true

// 1%
const slippage = Percentage.fromNumber(1)

const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const position = await fullSailSDK.Position.getById(positionId)

let currentEpochOSail
let oSailReward
if (position.staked && pool.gauge_id && !pool.gauge_killed) {
  currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()
  oSailReward = await fullSailSDK.Position.getOSailRewards({
    poolId,
    coinTypeA: chainPool.coinTypeA,
    coinTypeB: chainPool.coinTypeB,
    positionId,
    oSailCoinType: currentEpochOSail.address,
    gaugeId: pool.gauge_id,
  })
}

// Calculate the opposite coin amount based on the first coin amount and tick range
// This ensures proper liquidity ratio within the specified price range, including slippage
const { maxAmountB } = ClmmPoolUtil.estLiquidityAndCoinAmountFromOneAmounts(
  position.tick_lower,
  position.tick_upper,
  amountA,
  fixedAmountA,
  roundUp,
  slippage.toCoefficient(),
  chainPool.currentSqrtPrice,
)

const transaction = await fullSailSDK.Position.addLiquidityTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  positionId,
  tickLower: position.tick_lower,
  tickUpper: position.tick_upper,
  amountA,
  amountB: maxAmountB,
  slippage,
  fixedAmountA,
  currentSqrtPrice: chainPool.currentSqrtPrice,
  // params below are required only if position is staked
  gaugeId: pool.gauge_id,
  positionStakeId: position.stake_info?.id,
  oSailCoinType: currentEpochOSail?.address,
  oSailAmount: oSailReward,
  rewardChoice,
  // if rewardChoice is "vesail", you can provide your existing permanent lock id and oSAIL will be added to it
  // otherwise new lock will be created every call
  permanentLockId,
  newLockDurationDays: MAX_LOCK_DURATION_DAYS,
  newLockIsPermanent: true,
})

Stake position

Can be used only if position is created before gauge is added to the pool or if gaugeId was not provided when creating the position via Position.openTransaction(). Unstaked positions within a pool with gauge will receive only pool rewards. Only fees claimed automatically within this transaction. Pool rewards are not.

const poolId = '0x0...'
const positionId = '0x0...'

const position = await fullSailSDK.Position.getById(positionId)
const { pool } = await fullSailSDK.Pool.getById(poolId)

const transaction = await fullSailSDK.Position.stakeTransaction({
  coinTypeA: pool.token_a.address,
  coinTypeB: pool.token_b.address,
  poolId: pool.address,
  positionId: position.id,
  gaugeId: pool.gauge_id,
})

Unstake position

Should be used if gauge contract for the pool was killed (pool.gauge_killed is true) and position is staked. Staked positions within a pool with killed gauge will receive only pool rewards. Both oSAIL and pool rewards are claimed automatically within this transaction.

const poolId = '0x0...'
const positionId = '0x0...'

const position = await fullSailSDK.Position.getById(positionId)
const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()

const transaction = await fullSailSDK.Position.unstakeTransaction({
  coinTypeA: pool.token_a.address,
  coinTypeB: pool.token_b.address,
  poolId: pool.address,
  positionStakeId: position.stake_info.id,
  gaugeId: pool.gauge_id,
  rewardCoinTypes: chainPool.rewardCoinsInfo.map(({ coinType }) => coinType),
  oSailCoinType: currentEpochOSail.address,
})

Remove liquidity from position

Only oSAIL claimed automatically within this transaction. Fees and pool rewards are not.

import { MAX_LOCK_DURATION_DAYS, Percentage } from '@fullsailfinance/sdk'

const poolId = '0x0...'
const positionId = '0x0...'
// your existing permanent lock id
const permanentLockId = '0x0...'
// 'vesail' | 'sail' | 'usd'
const rewardChoice = 'vesail'

// liquidity amount to remove
const liquidity = 1000000n
// 1%
const slippage = Percentage.fromNumber(1)

const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const position = await fullSailSDK.Position.getById(positionId)

let currentEpochOSail
let oSailReward
if (position.staked && pool.gauge_id && !pool.gauge_killed) {
  currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()
  oSailReward = await fullSailSDK.Position.getOSailRewards({
    poolId,
    coinTypeA: chainPool.coinTypeA,
    coinTypeB: chainPool.coinTypeB,
    positionId,
    oSailCoinType: currentEpochOSail.address,
    gaugeId: pool.gauge_id,
  })
}

const transaction = await fullSailSDK.Position.removeLiquidityTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  positionId,
  tickLower: position.tick_lower,
  tickUpper: position.tick_upper,
  liquidity,
  slippage,
  currentSqrtPrice: chainPool.currentSqrtPrice,
  // params below are required only if position is staked
  gaugeId: pool.gauge_id,
  positionStakeId: position.stake_info?.id,
  oSailCoinType: currentEpochOSail?.address,
  oSailAmount: oSailReward,
  positionUpdatedAt: position.updated_at,
  rewardChoice,
  // if rewardChoice is "vesail", you can provide your existing permanent lock id and oSAIL will be added to it
  // otherwise new lock will be created every call
  permanentLockId,
  newLockDurationDays: MAX_LOCK_DURATION_DAYS,
  newLockIsPermanent: true,
})

Close position

All rewards claimed automatically within this transaction.

import { MAX_LOCK_DURATION_DAYS, Percentage } from '@fullsailfinance/sdk'

const poolId = '0x0...'
const positionId = '0x0...'
// your existing permanent lock id
const permanentLockId = '0x0...'
// 'vesail' | 'sail' | 'usd'
const rewardChoice = 'vesail'

// 1%
const slippage = Percentage.fromNumber(1)

const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const position = await fullSailSDK.Position.getById(positionId)

let currentEpochOSail
let oSailReward
if (position.staked && pool.gauge_id && !pool.gauge_killed) {
  currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()
  oSailReward = await fullSailSDK.Position.getOSailRewards({
    poolId,
    coinTypeA: chainPool.coinTypeA,
    coinTypeB: chainPool.coinTypeB,
    positionId,
    oSailCoinType: currentEpochOSail.address,
    gaugeId: pool.gauge_id,
  })
}

const transaction = await fullSailSDK.Position.closeTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  positionId,
  tickLower: position.tick_lower,
  tickUpper: position.tick_upper,
  currentSqrtPrice: chainPool.currentSqrtPrice,
  liquidity: BigInt(position.liquidity),
  slippage,
  // You MUST provide the exact reward coin list to claim all available rewards.
  rewardCoinTypes: chainPool.rewardCoinsInfo.map(({ coinType }) => coinType),
  // params below are required only if position is staked
  gaugeId: pool.gauge_id,
  positionStakeId: position.stake_info?.id,
  oSailCoinType: currentEpochOSail?.address,
  oSailAmount: oSailReward,
  rewardChoice,
  // if rewardChoice is "vesail", you can provide your existing permanent lock id and oSAIL will be added to it
  // otherwise new lock will be created every call
  permanentLockId,
  newLockDurationDays: MAX_LOCK_DURATION_DAYS,
  newLockIsPermanent: true,
})

Claim fee

Can be used only if position is not staked.

const poolId = '0x0...'
const positionId = '0x0...'

const { pool } = await fullSailSDK.Pool.getById(poolId)

const transaction = await fullSailSDK.Position.claimFeeTransaction({
  coinTypeA: pool.token_a.address,
  coinTypeB: pool.token_b.address,
  poolId,
  positionId,
})

Claim pool rewards for unstaked position

Can be used only if position is not staked.

const poolId = '0x0...'
const positionId = '0x0...'

const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)

const transaction = await fullSailSDK.Position.claimUnstakedPoolRewardsTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  positionId,
  rewardCoinTypes: chainPool.rewardCoinsInfo.map(({ coinType }) => coinType),
})

Claim all unstaked position rewards

Can be used only if position is not staked. It claims both fee and pool rewards.

const poolId = '0x0...'
const positionId = '0x0...'

const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)

const transaction = await fullSailSDK.Position.claimFeeAndUnstakedPoolRewardsTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  positionId,
  rewardCoinTypes: chainPool.rewardCoinsInfo.map(({ coinType }) => coinType),
})

Claim oSAIL

Can be used only if position is staked.

const poolId = '0x0...'
const positionId = '0x0...'

const { pool } = await fullSailSDK.Pool.getById(poolId)
const position = await fullSailSDK.Position.getById(positionId)
const currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()

const transaction = await fullSailSDK.Position.claimOSailTransaction({
  coinTypeA: pool.token_a.address,
  coinTypeB: pool.token_b.address,
  poolId,
  positionStakeId: position.stake_info.id,
  oSailCoinType: currentEpochOSail.address,
  gaugeId: pool.gauge_id,
})

Claim pool rewards for staked position

Can be used only if position is staked.

const poolId = '0x0...'
const positionId = '0x0...'

const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const position = await fullSailSDK.Position.getById(positionId)

const transaction = await fullSailSDK.Position.claimStakedPoolRewardsTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  positionStakeId: position.stake_info.id,
  rewardCoinTypes: chainPool.rewardCoinsInfo.map(({ coinType }) => coinType),
  gaugeId: pool.gauge_id,
})

Claim all staked position rewards

Claims both oSAIL and pool rewards for staked position.

const poolId = '0x0...'
const positionId = '0x0...'

const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const position = await fullSailSDK.Position.getById(positionId)
const currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()

const transaction = await fullSailSDK.Position.claimOSailAndStakedPoolRewardsTransaction({
  coinTypeA: chainPool.coinTypeA,
  coinTypeB: chainPool.coinTypeB,
  poolId,
  rewardCoinTypes: chainPool.rewardCoinsInfo.map(({ coinType }) => coinType),
  positionStakeId: position.stake_info.id,
  gaugeId: pool.gauge_id,
  oSailCoinType: currentEpochOSail?.address,
})

Claim all rewards for multiple positions

The combined method for claiming all posible rewards from multiple positions.

import { MAX_LOCK_DURATION_DAYS, Percentage } from '@fullsailfinance/sdk'

const poolId = '0x0...'
const positionId = '0x0...'
// your existing permanent lock id
const permanentLockId = '0x0...'
// 'vesail' | 'sail' | 'usd'
const rewardChoice = 'vesail'

// 1%
const slippage = Percentage.fromNumber(1)

const { pool } = await fullSailSDK.Pool.getById(poolId)
const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const position = await fullSailSDK.Position.getById(positionId)

let currentEpochOSail
let oSailReward
if (position.staked && pool.gauge_id && !pool.gauge_killed) {
  currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()
  oSailReward = await fullSailSDK.Position.getOSailRewards({
    poolId,
    coinTypeA: chainPool.coinTypeA,
    coinTypeB: chainPool.coinTypeB,
    positionId,
    oSailCoinType: currentEpochOSail.address,
    gaugeId: pool.gauge_id,
  })
}

const transaction = await fullSailSDK.Position.claimAllTransaction([
  {
    coinTypeA: chainPool.coinTypeA,
    coinTypeB: chainPool.coinTypeB,
    poolId,
    positionId,
    rewardCoinTypes: chainPool.rewardCoinsInfo.map(({ coinType }) => coinType),
    // params below are required only if position is staked
    gaugeId: pool.gauge_id,
    positionStakeId: position.stake_info?.id,
    oSailCoinType: currentEpochOSail?.address,
    oSailAmount: oSailReward,
    positionUpdatedAt: position.updated_at,
    rewardChoice,
    slippage,
    // if rewardChoice is "vesail", you can provide your existing permanent lock id and oSAIL will be added to it
    // otherwise new lock will be created every call
    permanentLockId,
    newLockDurationDays: MAX_LOCK_DURATION_DAYS,
    newLockIsPermanent: true,
  },
])

Swap

Uses Cetus Aggregator to swap coins. See Cetus Aggregator docs for more details.

import { Percentage } from '@fullsailfinance/sdk'

const from = '0x0...'
const target = '0x0...'
const amount = 1000000n

// 1%
const slippage = Percentage.fromNumber(1)

// findRouters method from Cetus Aggregator
const router = await fullSailSDK.Swap.getSwapRoute({
  from,
  target,
  amount,
})

// routerSwap method from Cetus Aggregator
const transaction = await fullSailSDK.Swap.swapRouterTransaction({
  router,
  slippage: slippage.toCoefficient(),
})

Swaps coins directly through smart contract.

import { Percentage } from '@fullsailfinance/sdk'

const poolId = '0x0...'
const coinInType = '0x0...'
const coinOutType = '0x0...'

const slippage = Percentage.fromNumber(1)
const amount = 1000000n
const byAmountIn = true

const chainPool = await fullSailSDK.Pool.getByIdFromChain(poolId)
const coinIn = await fullSailSDK.Coin.getByType(coinInType)
const coinOut = await fullSailSDK.Coin.getByType(coinOutType)

// checking swap direction
const isAtoB = chainPool.coinTypeA === coinInType

// calculates estimated amounts, price after swap, and returns some of method params as swap params for convinience
const presSwap = await fullSailSDK.Swap.preSwap({
  coinTypeA: isAtoB ? coinInType : coinOutType,
  coinTypeB: isAtoB ? coinOutType : coinInType,
  decimalsA: isAtoB ? coinIn.decimals : coinOut.decimals,
  decimalsB: isAtoB ? coinOut.decimals : coinIn.decimals,
  poolId,
  amount,
  byAmountIn,
  isAtoB,
  currentSqrtPrice: chainPool.currentSqrtPrice,
})

const transaction = await fullSailSDK.Swap.swapTransaction({
  amount,
  amountLimit: byAmountIn ? presSwap.estimatedAmountOut : presSwap.estimatedAmountIn,
  slippage,
  ...presSwap.swapParams,
})

Locks

Create lock

Creates lock using SAIL.

import { MAX_LOCK_DURATION_DAYS } from '@fullsailfinance/sdk'

// 1 SAIL
const amount = 1000000n

const transaction = await fullSailSDK.Lock.createLockTransaction({
  amount,
  isPermanent: true,
  durationDays: MAX_LOCK_DURATION_DAYS,
})

Creates lock using oSAIL.

import { MAX_LOCK_DURATION_DAYS } from '@fullsailfinance/sdk'

const oSailCoinType = '0x0...'

// 1 oSAIL
const amount = 1000000n

const transaction = await fullSailSDK.Lock.createLockFromOSailTransaction({
  amount,
  oSailCoinType,
  isPermanent: true,
  durationDays: MAX_LOCK_DURATION_DAYS,
})

Claim oSAIL and create lock

Combines Position.claimOSailTransaction() and Lock.createLockFromOSailTransaction() for convinience.

import { MAX_LOCK_DURATION_DAYS } from '@fullsailfinance/sdk'

const poolId = '0x0...'
const positionId = '0x0...'

const { pool } = await fullSailSDK.Pool.getById(poolId)
const position = await fullSailSDK.Position.getById(positionId)
const currentEpochOSail = await fullSailSDK.Coin.getCurrentEpochOSail()

const transaction = await fullSailSDK.Lock.claimOSailAndCreateLockTransaction({
  coinTypeA: pool.token_a.address,
  coinTypeB: pool.token_b.address,
  poolId,
  gaugeId: pool.gauge_id,
  positionStakeId: position.stake_info.id,
  oSailCoinType: currentEpochOSail.address,
  durationDays: MAX_LOCK_DURATION_DAYS,
  isPermanent: true,
})

Increase lock amount

Increases lock by provided SAIL amount.

const lockId = '0x0...'

// 1 SAIL
const amount = 1000000n

const transaction = await fullSailSDK.Lock.increaseAmountTransaction({
  lockId,
  amount,
})

Merge locks

Merges two locks into one. If one of the locks is used for voting, votes from this lock will be reset, and user will need to vote again.

const fromLockId = '0x0...'
const toLockId = '0x0...'

const transaction = await fullSailSDK.Lock.mergeTransaction({
  fromLockId,
  toLockId,
  isFromLockVoted: true,
  isToLockVoted: false,
})

Split lock

Splits lock into two locks by SAIL amount. If lock is used for voting, votes from this lock will be reset, and user will need to vote again.

const lockId = '0x0...'

// 1 SAIL
const amount = 1000000n

const transaction = await fullSailSDK.Lock.splitTransaction({
  lockId,
  amount,
  isVoted: true,
})

Transfer lock

Transfers lock to another wallet.

const lockId = '0x0...'
const receiver = '0x0...'

const transaction = await fullSailSDK.Lock.transferTransaction({
  lockId,
  receiver,
})

Increase lock duration

const lockId = '0x0...'
// 4 years
const durationDays = 365 * 4

const transaction = await fullSailSDK.Lock.increaseDurationTransaction({
  lockId,
  durationDays,
})

Toggle isPermanent

Enables isPermanent flag for lock.

const lockId = '0x0...'

const transaction = await fullSailSDK.Lock.enablePermanentTransaction({
  lockId,
})

Disables isPermanent flag for lock.

const lockId = '0x0...'

const transaction = await fullSailSDK.Lock.disablePermanentTransaction({
  lockId,
})

Vote

Votes using all locks.

weight is in abstract units to calculate voting power ratio. One weight cannot be more than 10000. Sum of weights will be used as 100%. For example you can provide weights [20, 80] or [1, 1] and it will work fine. In case of [20, 80] total weight is 100 (similarly to 100%). First pool will receve 20/100 (20%) of voting power and second pool will receive 80/100 (80%) of voting power. In case of [1, 1] total weight is 2. First pool will receve 1/2 (50%) of voting power and second pool will receive 1/2 (50%) of voting power.

volume is predicted volume of pool for next epoch in USD with decimals 6.

const lockId1 = '0x0...'
const lockId2 = '0x0...'
const lockId3 = '0x0...'

const poolId1 = '0x0...'
const poolId2 = '0x0...'

const weight1 = 20n
const weight2 = 80n

// 1 USD
const volume1 = 1000000n
// 2 USD
const volume2 = 2000000n

const transaction = await fullSailSDK.Lock.batchVoteTransaction({
  // locks will be used for voting
  lockIds: [lockId1, lockId2, lockId3],
  // each array item is a vote for pool
  votes: [
    { poolId: poolId1, weight: weight1, volume: volume1 },
    { poolId: poolId2, weight: weight2, volume: volume2 },
  ],
})