@fullsailfinance/sdk
v8.3.0
Published
SDK for FullSail ve(4,4) dex
Keywords
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/sdkyarn:
$ yarn add @fullsailfinance/sdkConfiguration
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 poolcurrentSqrtPrice: 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 poolgauge_killed: can betrueif 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 rangestake_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:
"vesail"- lock it into veSAIL to participate in governance and earn trading fees."sail"- redeem it for liquid SAIL in a 2 to 1 ratio (100 oSAIL will be redeemed for 50 SAIL)."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 notvoting_power: current voting power provided by this lock. Reduces slowly over time if lock is not permanentis_voting_onchain: whether lock is used for voting at current epochamount: 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
- Add liquidity to position
- Stake position
- Unstake position
- Remove Liquidity from position
- Close position
- Claim fee
- Claim pool rewards for unstaked position
- Claim all unstaked position rewards
- Claim oSAIL
- Claim pool rewards for staked position
- Claim all staked position rewards
- Claim all rewards for multiple 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 (using SAIL or oSAIL)
- Claim oSAIL and create lock
- Increase lock amount
- Merge locks
- Split lock
- Increase lock duration
- Toggle isPermanent
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 },
],
})