# Table of Contents - [via SDK | Cetus Developer Docs](#via-sdk-cetus-developer-docs) - [Prerequisites | Cetus Developer Docs](#prerequisites-cetus-developer-docs) - [Getting Started | Cetus Developer Docs](#getting-started-cetus-developer-docs) - [Features Available | Cetus Developer Docs](#features-available-cetus-developer-docs) - [Get reward | Cetus Developer Docs](#get-reward-cetus-developer-docs) - [Get clmm pools | Cetus Developer Docs](#get-clmm-pools-cetus-developer-docs) - [Get positions | Cetus Developer Docs](#get-positions-cetus-developer-docs) - [Partner swap | Cetus Developer Docs](#partner-swap-cetus-developer-docs) - [Fee | Cetus Developer Docs](#fee-cetus-developer-docs) - [Changelog | Cetus Developer Docs](#changelog-cetus-developer-docs) - [Create clmm pool | Cetus Developer Docs](#create-clmm-pool-cetus-developer-docs) - [Price impact | Cetus Developer Docs](#price-impact-cetus-developer-docs) - [Collect fees | Cetus Developer Docs](#collect-fees-cetus-developer-docs) - [Price, tick index and sqrt price correlation calculation | Cetus Developer Docs](#price-tick-index-and-sqrt-price-correlation-calculation-cetus-developer-docs) - [Get ticks | Cetus Developer Docs](#get-ticks-cetus-developer-docs) - [Open position | Cetus Developer Docs](#open-position-cetus-developer-docs) - [Getting Started | Cetus Developer Docs](#getting-started-cetus-developer-docs) - [Add liquidity | Cetus Developer Docs](#add-liquidity-cetus-developer-docs) - [Swap | Cetus Developer Docs](#swap-cetus-developer-docs) - [Liquidity and coin amounts calculation | Cetus Developer Docs](#liquidity-and-coin-amounts-calculation-cetus-developer-docs) - [Collect rewards | Cetus Developer Docs](#collect-rewards-cetus-developer-docs) - [Preswap | Cetus Developer Docs](#preswap-cetus-developer-docs) - [Close position | Cetus Developer Docs](#close-position-cetus-developer-docs) - [Smart router v1 | Cetus Developer Docs](#smart-router-v1-cetus-developer-docs) - [Smart router v2 | Cetus Developer Docs](#smart-router-v2-cetus-developer-docs) - [via Contract | Cetus Developer Docs](#via-contract-cetus-developer-docs) - [APR correlation calculation | Cetus Developer Docs](#apr-correlation-calculation-cetus-developer-docs) - [Remove liquidity | Cetus Developer Docs](#remove-liquidity-cetus-developer-docs) - [Minimum received & Maximum sold | Cetus Developer Docs](#minimum-received-maximum-sold-cetus-developer-docs) - [Data Structure | Cetus Developer Docs](#data-structure-cetus-developer-docs) --- # via SDK | Cetus Developer Docs [PreviousDev Overview](/cetus-developer-docs) [NextGetting Started](/cetus-developer-docs/developer/via-sdk/getting-started) Last updated 9 months ago Please refer to the following modules to learn how to integrate with Cetus Protocol via our Typescript SDK. 💻 [Getting Started](/cetus-developer-docs/developer/via-sdk/getting-started) [Prerequisites](/cetus-developer-docs/developer/via-sdk/prerequisites) [Features Available](/cetus-developer-docs/developer/via-sdk/features-available) --- # Prerequisites | Cetus Developer Docs [](#id-1.-npm-install) 1\. **NPM install** ----------------------------------------------- Copy npm i @cetusprotocol/cetus-sui-clmm-sdk [](#setting-up-configuration) 2\. Setting Up Configuration --------------------------------------------------------------- Cetus Typescript SDK now includes a default initialization method that allows for quick generation of the Cetus SDK configuration. You can utilize the `src/config/initCetusSDK` method to swiftly initialize the configuration. You have the option to select either 'mainnet' or 'testnet' for the network. Copy import { initCetusSDK } from '@cetusprotocol/cetus-sui-clmm-sdk' const cetusClmmSDK = initCetusSDK({network: 'mainnet'}) If you wish to set your own full node URL and simulate address, you can do so as follows: Copy import { initCetusSDK } from '@cetusprotocol/cetus-sui-clmm-sdk' const network = 'mainnet'; const fullNodeUrl = "YOUR_FULL_NODE_URL" const wallet = "YOUR_WALLET_ADDRESS" const cetusClmmSDK = initCetusSDK({network, fullNodeUrl, wallet}) Now, you can start using Cetus SDK! [PreviousGetting Started](/cetus-developer-docs/developer/via-sdk/getting-started) [NextFeatures Available](/cetus-developer-docs/developer/via-sdk/features-available) Last updated 24 days ago --- # Getting Started | Cetus Developer Docs [Previousvia SDK](/cetus-developer-docs/developer/via-sdk) [NextPrerequisites](/cetus-developer-docs/developer/via-sdk/prerequisites) Last updated 25 days ago [](#introduction) Introduction ----------------------------------- cetus-sui-clmm-sdk is the official software development kit (SDK) specifically designed for seamless integration with cetus clmm. It provides developers with the necessary tools and resources to easily connect and interact with cetus clmm, enabling the development of robust and efficient applications. [](#latest-packages-address-and-npm-version) Latest packages address and npm version ----------------------------------------------------------------------------------------- 1. [latest packages address](/cetus-developer-docs#latest-contract-address) 2. [latest npm version](/cetus-developer-docs#latest-npm-package-version) [![Logo](https://static-production.npmjs.com/1996fcfdf7ca81ea795f67f093d7f449.png)npm: @cetusprotocol/cetus-sui-clmm-sdknpm](https://www.npmjs.com/package/@cetusprotocol/cetus-sui-clmm-sdk) [![Logo](https://github.com/fluidicon.png)GitHub - CetusProtocol/cetus-clmm-sui-sdk: The clmm sdk on Sui.GitHub](https://github.com/CetusProtocol/cetus-clmm-sui-sdk) --- # Features Available | Cetus Developer Docs ### [](#id-1.-get-data) 1\. Get data 1.1 [Get clmm pools](/cetus-developer-docs/developer/via-sdk/features-available/get-clmm-pools) 1.2 [Get positions](/cetus-developer-docs/developer/via-sdk/features-available/get-positions) 1.3 [Get reward](/cetus-developer-docs/developer/via-sdk/features-available/get-reward) 1.4 [Get ticks](/cetus-developer-docs/developer/via-sdk/features-available/get-ticks) ### [](#id-2.-pools-and-postions) 2\. Pools and postions 2.1 [Create clmm pool](/cetus-developer-docs/developer/via-sdk/features-available/create-clmm-pool) 2.2 [Open position](/cetus-developer-docs/developer/via-sdk/features-available/open-position) 2.3 [Add liquidity](/cetus-developer-docs/developer/via-sdk/features-available/add-liquidity) 2.4 [Remove liquidity](/cetus-developer-docs/developer/via-sdk/features-available/remove-liquidity) 2.5 [Close position](/cetus-developer-docs/developer/via-sdk/features-available/close-position) 2.6 [Collect fees](/cetus-developer-docs/developer/via-sdk/features-available/collect-fees) 2.7 [Collect rewards](/cetus-developer-docs/developer/via-sdk/features-available/collect-rewards) ### [](#id-3.-swap) 3\. Swap 3.1 [Pre Swap](/cetus-developer-docs/developer/via-sdk/features-available/preswap) 3.2 [Swap](/cetus-developer-docs/developer/via-sdk/features-available/swap) 3.3 [Partner swap](/cetus-developer-docs/developer/via-sdk/features-available/partner-swap) 3.4 [Smart router v1](/cetus-developer-docs/developer/via-sdk/features-available/smart-router-v1) 3.5 [Smart router v2](/cetus-developer-docs/developer/via-sdk/features-available/smart-router-v2) 3.6 [Price impact](/cetus-developer-docs/developer/via-sdk/features-available/price-impact) 3.7 [Minimum received & Maximum sold](/cetus-developer-docs/developer/via-sdk/features-available/minimum-received-and-maximum-sold) 3.8 [Fee](/cetus-developer-docs/developer/via-sdk/features-available/fee) ### [](#id-4.-liquidity-correlation-calculation) 4\. Liquidity correlation calculation 4.1 [Liquidity correlation calculation](/cetus-developer-docs/developer/via-sdk/features-available/liquidity-and-coin-amounts-calculation) ### [](#id-5.-apr-correlation-calculation) 5\. APR correlation calculation 5.1 [Pool APR](/cetus-developer-docs/developer/via-sdk/features-available/apr-correlation-calculation) 5.2 [Position APR](/cetus-developer-docs/developer/via-sdk/features-available/apr-correlation-calculation#id-2.-position-apr) [PreviousPrerequisites](/cetus-developer-docs/developer/via-sdk/prerequisites) [NextGet clmm pools](/cetus-developer-docs/developer/via-sdk/features-available/get-clmm-pools) Last updated 2 months ago 💻 --- # Get reward | Cetus Developer Docs [](#id-1.-get-the-position-reward-list-of-one-pool) 1\. Get the position reward list of one pool ----------------------------------------------------------------------------------------------------- use `SDK.Pool.fetchPositionRewardList()` method #### [](#function-input-params) Function input params * poolID: The pool object ID. * coinTypeA: Coin A type. * coinTypeB: Coin B type. #### [](#example) Example Copy async function getRewardListOfOnePool() { const poolId = '0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160' const pool = await TestnetSDK.Pool.getPool(poolId) const res = await TestnetSDK.Pool.fetchPositionRewardList({ pool_id: pool.poolAddress, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, }) console.log('retrieva reward list of one pool', res) } // getRewardListOfOnePool() /* { liquidity: '1178890675', tick_lower_index: -2, tick_upper_index: 2, reward_amount_owed_0: '0', reward_amount_owed_1: '0', reward_amount_owed_2: '0', reward_growth_inside_0: '0', reward_growth_inside_1: '0', reward_growth_inside_2: '0', fee_growth_inside_a: '0', fee_owed_a: '0', fee_growth_inside_b: '0', fee_owed_b: '0', pos_object_id: '0x88e9779719cdb9d5e722267ca2ddd0681d6c845eadfe4f6e46f9e456b26ad15e' }, ... { liquidity: '496569205127', tick_lower_index: -6, tick_upper_index: 4, reward_amount_owed_0: '0', reward_amount_owed_1: '0', reward_amount_owed_2: '0', reward_growth_inside_0: '0', reward_growth_inside_1: '0', reward_growth_inside_2: '0', fee_growth_inside_a: '0', fee_owed_a: '0', fee_growth_inside_b: '0', fee_owed_b: '0', pos_object_id: '0x004dcb4665475ed18b3327e35cdbd6360ce1028d08bec185bafdbfb57d2ef085' }, */ [](#id-2.-get-the-daily-reward-emission-info-for-one-pool) 2\. Get the daily reward emission info for one pool ------------------------------------------------------------------------------------------------------------------- use `sdk.Rewarder.emissionsEveryDay()` method #### [](#function-input-params-1) Function input params * poolID: The pool object ID. #### [](#example-1) Example Copy async function getRewardEmissionInfosForOnePoolEveryDay() { const poolObjectId = '0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160' const emissionsEveryDay = await TestnetSDK.Rewarder.emissionsEveryDay(poolObjectId) console.log({ emissionsEveryDay }) } // getRewardEmissionInfosForOnePoolEveryDay() /* { emissionsEveryDay: [\ {\ emissions: 86400000000,\ coin_address: '0x0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdc::USDC'\ },\ {\ emissions: 0,\ coin_address: '0x0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdt::USDT'\ },\ {\ emissions: 0,\ coin_address: '0x0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::cetus::CETUS'\ }\ ] } */ [](#id-3.-get-rewards-of-position) 3\. Get rewards of position ------------------------------------------------------------------- use `sdk.Rewarder.betchFetchPositionRewarders()` method #### [](#function-input-params-2) Function input params * positionIDs: Array of position object IDs. #### [](#example-2) Example Copy async function getPositionRewardAmount() { const pool = await TestnetSDK.Pool.getPool('0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160') const posRewardersAmount = await TestnetSDK.Rewarder.batchFetchPositionRewarders( ['0xf10d37cc00bcd60f85cef3fe473ea979e3f7f3631d522618e80c876b349e56bc'] ) console.log({ posRewardersAmount }) } //getPositionRewardAmount() /* { posRewardersAmount: [\ {\ amount_owed: ,\ coin_address: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdc::USDC'\ },\ {\ amount_owed: ,\ coin_address: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdt::USDT'\ },\ {\ amount_owed: ,\ coin_address: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::cetus::CETUS'\ }\ ] } */ [PreviousGet positions](/cetus-developer-docs/developer/via-sdk/features-available/get-positions) [NextGet ticks](/cetus-developer-docs/developer/via-sdk/features-available/get-ticks) Last updated 2 months ago --- # Get clmm pools | Cetus Developer Docs [](#id-1.-get-all-pools) 1\. Get all pools ----------------------------------------------- use `sdk.Pool.getPoolsWithPage()` method #### [](#function-input-params) Function input params * assignPools: An array of pool IDs to get. If you want to get all pools, just pass an empty array. #### [](#example) Example Copy async function getAllPools() { // If you want to get all pools, just pass one empty array. const pools = await TestnetSDK.Pool.getPoolsWithPage([]) console.log(`pool length: ${pools.length}`) } // getAllPools() //pool length: 82 [](#id-2.-batch-get-pools) 2\. Batch get pools --------------------------------------------------- use `sdk.Pool.getPoolsWithPage()` method #### [](#function-input-params-1) Function input params * assignPools: An array of pool IDs to get. If you want to get all pools, just pass an empty array, otherwise pass an array not null. #### [](#example-1) Example Copy async function batchGetPools(){ const betch_pool_addresses = [\ '0xbed3136f15b0ea649fb94bcdf9d3728fb82ba1c3e189bf6062d78ff547850054',\ '0x74dcb8625ddd023e2ef7faf1ae299e3bc4cb4c337d991a5326751034676acdae',\ ] // if pool addresses not empty, you will get the pool list of the addresses. const betch_pools = await TestnetSDK.Pool.getPoolsWithPage(betch_pool_addresses) console.log({ betch_pools }) } //batchGetPools() /* { betch_pools: [\ {\ poolAddress: '0xbed3136f15b0ea649fb94bcdf9d3728fb82ba1c3e189bf6062d78ff547850054',\ poolType: '0x0868b71c0cba55bf0faf6c40df8c179c67a4d0ba0e79965b68b3d72d7dfbf666::pool::Pool<0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdt::USDT, 0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::cetus::CETUS>',\ coinTypeA: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdt::USDT',\ coinTypeB: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::cetus::CETUS',\ coinAmountA: '301095941257',\ coinAmountB: '7744151970817830',\ current_sqrt_price: '2958038090622808503233',\ current_tick_index: 101552,\ fee_growth_global_a: '105486819403232',\ fee_growth_global_b: '5375007645466054573',\ fee_protocol_coin_a: '57258995',\ fee_protocol_coin_b: '2345233787348',\ fee_rate: '2500',\ is_pause: false,\ liquidity: '48272892630439',\ position_manager: [Object],\ rewarder_infos: [Array],\ rewarder_last_updated_time: '1690775362',\ tickSpacing: 60,\ ticks_handle: '0x7ac1074ec3dc1bcbffc4fdaa366464a9402f17a36a2bfd81afa0ee97230dcf95',\ uri: 'https://bq7bkvdje7gvgmv66hrxdy7wx5h5ggtrrnmt66rdkkehb64rvz3q.arweave.net/DD4VVGknzVMyvvHjceP2v0_TGnGLWT96I1KIcPuRrnc',\ index: 47,\ name: 'USDT-CETUS[60]'\ },\ {\ poolAddress: '0x74dcb8625ddd023e2ef7faf1ae299e3bc4cb4c337d991a5326751034676acdae',\ poolType: '0x0868b71c0cba55bf0faf6c40df8c179c67a4d0ba0e79965b68b3d72d7dfbf666::pool::Pool<0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdc::USDC, 0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::eth::ETH>',\ coinTypeA: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdc::USDC',\ coinTypeB: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::eth::ETH',\ coinAmountA: '3322014941305',\ coinAmountB: '9107325795',\ current_sqrt_price: '28528838400056161926',\ current_tick_index: 8720,\ fee_growth_global_a: '1379094722374781659889726',\ fee_growth_global_b: '172841952761357607431',\ fee_protocol_coin_a: '3320806164020',\ fee_protocol_coin_b: '61436182',\ fee_rate: '2500',\ is_pause: false,\ liquidity: '1818716850',\ position_manager: [Object],\ rewarder_infos: [Array],\ rewarder_last_updated_time: '1690775362',\ tickSpacing: 60,\ ticks_handle: '0xba76b336b750760b26a524f8c56e8b74a6f247739e15c423cba1d2171dfaf5f1',\ uri: 'https://bq7bkvdje7gvgmv66hrxdy7wx5h5ggtrrnmt66rdkkehb64rvz3q.arweave.net/DD4VVGknzVMyvvHjceP2v0_TGnGLWT96I1KIcPuRrnc',\ index: 8,\ name: 'USDC-ETH[60]'\ }\ ] } */ [](#id-3.-get-one-pool) 3\. Get one pool --------------------------------------------- use `sdk.Pool.getPool()` method #### [](#function-input-params-2) Function input params * poolID:pool address * forceRefresh: if refresh in cache. #### [](#example-2) Example Copy async function getOnePool() { const pool = await TestnetSDK.Pool.getPool('0xbed3136f15b0ea649fb94bcdf9d3728fb82ba1c3e189bf6062d78ff547850054') console.log({ pool }) } //getOnePool() /*{ pool: { poolAddress: '0xbed3136f15b0ea649fb94bcdf9d3728fb82ba1c3e189bf6062d78ff547850054', poolType: '0x0868b71c0cba55bf0faf6c40df8c179c67a4d0ba0e79965b68b3d72d7dfbf666::pool::Pool<0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdt::USDT, 0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::cetus::CETUS>', coinTypeA: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdt::USDT', coinTypeB: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::cetus::CETUS', coinAmountA: '301095941257', coinAmountB: '7744151970817830', current_sqrt_price: '2958038090622808503233', current_tick_index: 101552, fee_growth_global_a: '105486819403232', fee_growth_global_b: '5375007645466054573', fee_protocol_coin_a: '57258995', fee_protocol_coin_b: '2345233787348', fee_rate: '2500', is_pause: false, liquidity: '48272892630439', position_manager: { positions_handle: '0x5cb2c58574b34cd13dbd177bef53ab52b814131d0b684cf2b53f1d5d31d2d9f5', size: '4' }, rewarder_infos: [ [Object] ], rewarder_last_updated_time: '1690775362', tickSpacing: 60, ticks_handle: '0x7ac1074ec3dc1bcbffc4fdaa366464a9402f17a36a2bfd81afa0ee97230dcf95', uri: 'https://bq7bkvdje7gvgmv66hrxdy7wx5h5ggtrrnmt66rdkkehb64rvz3q.arweave.net/DD4VVGknzVMyvvHjceP2v0_TGnGLWT96I1KIcPuRrnc', index: 47, name: 'USDT-CETUS[60]' } } */ [](#id-4.-get-one-pool-by-coin-types-and-fee-rate) 4\. Get one pool by coin types and fee rate --------------------------------------------------------------------------------------------------- use `sdk.Pool.`getPoolByCoins`()` method #### [](#function-input-params-3) Function input params * **coinTypes**:coin types array. * **feeRate(Option)**: [fee rate](/cetus-developer-docs/developer/via-sdk/features-available/create-clmm-pool#function-input-params) number. #### [](#example-3) Example Copy async function getPoolByCoins() { const coinA = '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN' const coinB = '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN' const pools = await sdk.Pool.getPoolByCoins([coinA, coinB]) console.log('find pools by cointypes', pools) } //getPoolByCoins() /*[\ {\ poolAddress: '0xc8d7a1503dc2f9f5b05449a87d8733593e2f0f3e7bffd90541252782e4d2ca20',\ poolType: '0x1eabed72c53feb3805120a081dc15963c204dc8d091542592abaf7a35689b2fb::pool::Pool<0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN, 0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN>',\ coinTypeA: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN',\ coinTypeB: '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN',\ coinAmountA: '28955507725676',\ coinAmountB: '10709774839936',\ current_sqrt_price: '18450710277837054194',\ current_tick_index: 4,\ fee_growth_global_a: '68356588248388',\ fee_growth_global_b: '68640314597926',\ fee_protocol_coin_a: '252354404',\ fee_protocol_coin_b: '181369214',\ fee_rate: '100',\ is_pause: false,\ liquidity: '272265400952922972',\ position_manager: {\ positions_handle: '0x305866847f16ec900dc066e54664e4b0acd60115649de73586e544e2750658ae',\ size: '4382'\ },\ rewarder_infos: [ [Object], [Object], [Object] ],\ rewarder_last_updated_time: '1724747641',\ tickSpacing: 2,\ ticks_handle: '0x471d30a44388756ae2aae81e2ed313e7cce31b767b688936abd6930eeecd93e2',\ uri: 'https://reb6vnedll4q6tlu63cmk7iu3y252525bgh3zf7tq5onis572pfq.arweave.net/iQPqtINa-Q9NdPbExX0U3jXdd10Jj7yX84dc1Eu_08s',\ index: 1,\ name: 'COIN-COIN[2]'\ },\ {\ poolAddress: '0x737fa000d04878cdbc6a039e7741408c77cff4a573776aba7ec3bfc585d012d5',\ poolType: '0x1eabed72c53feb3805120a081dc15963c204dc8d091542592abaf7a35689b2fb::pool::Pool<0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN, 0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN>',\ coinTypeA: '0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN',\ coinTypeB: '0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN',\ coinAmountA: '18390698',\ coinAmountB: '19254697',\ current_sqrt_price: '18452109549321419309',\ current_tick_index: 5,\ fee_growth_global_a: '7218122745989279',\ fee_growth_global_b: '7253325707896047',\ fee_protocol_coin_a: '295931',\ fee_protocol_coin_b: '181754',\ fee_rate: '10000',\ is_pause: false,\ liquidity: '1662852544',\ position_manager: {\ positions_handle: '0x25d083bc89bbb45e38ca987da3733a6b4797d9ab79f5eeecbf7f50d988664082',\ size: '5'\ },\ rewarder_infos: [],\ rewarder_last_updated_time: '1721198005',\ tickSpacing: 200,\ ticks_handle: '0xcaf5d0883df638a6ee03393a8d6635ef8d38b2a0b8b19801f77fcfd5ff925955',\ uri: 'https://bq7bkvdje7gvgmv66hrxdy7wx5h5ggtrrnmt66rdkkehb64rvz3q.arweave.net/DD4VVGknzVMyvvHjceP2v0_TGnGLWT96I1KIcPuRrnc',\ index: 221,\ name: 'COIN-COIN[200]'\ }\ ] */ [PreviousFeatures Available](/cetus-developer-docs/developer/via-sdk/features-available) [NextGet positions](/cetus-developer-docs/developer/via-sdk/features-available/get-positions) Last updated 2 months ago 💻 --- # Get positions | Cetus Developer Docs [](#id-1.-get-all-positions-of-one-pool-by-owneraddress) 1\. Get all positions of one pool by `ownerAddress` ----------------------------------------------------------------------------------------------------------------- use `sdk.Position.getPositionList()` method #### [](#function-input-params) Function input params * `accountAddress`: The user account address. * `assignPoolIDs`: An array of pool ID. * `showDisplay`: When some testnet rpc nodes can't return object's display data, you can set this option to false, avoid returning errors. default set true. #### [](#example) Example Copy async function getPositions() { const res = await TestnetSDK.Position.getPositionList('0xcd0247d0b67e53dde69b285e7a748e3dc390e8a5244eb9dd9c5c53d95e4cf0aa', [\ '0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160',\ ], false) console.log('get positions of one pool by owner address', res) } // getPositions(() /* { creator: 'Cetus', description: 'Cetus Liquidity Position', image_url: 'https://bq7bkvdje7gvgmv66hrxdy7wx5h5ggtrrnmt66rdkkehb64rvz3q.arweave.net/DD4VVGknzVMyvvHjceP2v0_TGnGLWT96I1KIcPuRrnc', link: 'https://app.cetus.zone/position?chain=sui&id=0xf10d37cc00bcd60f85cef3fe473ea979e3f7f3631d522618e80c876b349e56bc', name: 'Cetus LP | Pool0-36', project_url: 'https://cetus.zone', pos_object_id: '0xf10d37cc00bcd60f85cef3fe473ea979e3f7f3631d522618e80c876b349e56bc', owner: '0xcd0247d0b67e53dde69b285e7a748e3dc390e8a5244eb9dd9c5c53d95e4cf0aa', type: '0x0868b71c0cba55bf0faf6c40df8c179c67a4d0ba0e79965b68b3d72d7dfbf666::position::Position', coin_type_a: '0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdt::USDT', coin_type_b: '0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdc::USDC', liquidity: '0', tick_lower_index: -2, tick_upper_index: 2, index: '36', pool: '0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160', reward_amount_owed_0: '0', reward_amount_owed_1: '0', reward_amount_owed_2: '0', reward_growth_inside_0: '0', reward_growth_inside_1: '0', reward_growth_inside_2: '0', fee_growth_inside_a: '0', fee_owed_a: '0', fee_growth_inside_b: '0', fee_owed_b: '0', position_status: 'Exists' }, ... { creator: 'Cetus', description: 'Cetus Liquidity Position', image_url: 'https://bq7bkvdje7gvgmv66hrxdy7wx5h5ggtrrnmt66rdkkehb64rvz3q.arweave.net/DD4VVGknzVMyvvHjceP2v0_TGnGLWT96I1KIcPuRrnc', link: 'https://app.cetus.zone/position?chain=sui&id=0xfbf94213d59d285f66bacdb3d667a4db00b491af35887022e9197bb244705bde', name: 'Cetus LP | Pool0-22', project_url: 'https://cetus.zone', pos_object_id: '0xfbf94213d59d285f66bacdb3d667a4db00b491af35887022e9197bb244705bde', owner: '0xcd0247d0b67e53dde69b285e7a748e3dc390e8a5244eb9dd9c5c53d95e4cf0aa', type: '0x0868b71c0cba55bf0faf6c40df8c179c67a4d0ba0e79965b68b3d72d7dfbf666::position::Position', coin_type_a: '0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdt::USDT', coin_type_b: '0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdc::USDC', liquidity: '0', tick_lower_index: -2, tick_upper_index: 2, index: '22', pool: '0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160', reward_amount_owed_0: '0', reward_amount_owed_1: '0', reward_amount_owed_2: '0', reward_growth_inside_0: '0', reward_growth_inside_1: '0', reward_growth_inside_2: '0', fee_growth_inside_a: '0', fee_owed_a: '0', fee_growth_inside_b: '0', fee_owed_b: '0', position_status: 'Exists' } */ [](#id-2.-get-all-positions-of-one-pool) 2\. Get all positions of one pool ------------------------------------------------------------------------------- use `sdk.Pool.getPositionList()` method. #### [](#function-input-params-1) Function input params * `positionHandle`: The position handle of pool. #### [](#example-1) Example Copy async function getPositionOfOnePool() { const pool = await TestnetSDK.Pool.getPool('0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160') const res = await TestnetSDK.Pool.getPositionList(pool.position_manager.positions_handle) console.log('get positions of one pool, the length of positions is: ', res.length) } //get positions of one pool, the length of positions is: 35 [](#id-3.-get-one-position) 3\. Get one position ----------------------------------------------------- use `sdk.Position.getPositionById()` method. #### [](#function-input-params-2) Function input params * `positionID`: The position object ID. * `calculateRewarder` :Whether to calculate the rewarder of the position. * `showDisplay`: When some testnet rpc nodes can't return object's display data, you can set this option to false, avoid returning errors. default set true. #### [](#example-2) Example Copy async function getPositionById() { const res = await TestnetSDK.Position.getPositionById('0xfbf94213d59d285f66bacdb3d667a4db00b491af35887022e9197bb244705bde') console.log('get position by id', res) } // getPositionById() /* get position by id { creator: 'Cetus', description: 'Cetus Liquidity Position', image_url: 'https://bq7bkvdje7gvgmv66hrxdy7wx5h5ggtrrnmt66rdkkehb64rvz3q.arweave.net/DD4VVGknzVMyvvHjceP2v0_TGnGLWT96I1KIcPuRrnc', link: 'https://app.cetus.zone/position?chain=sui&id=0xfbf94213d59d285f66bacdb3d667a4db00b491af35887022e9197bb244705bde', name: 'Cetus LP | Pool0-22', project_url: 'https://cetus.zone', pos_object_id: '0xfbf94213d59d285f66bacdb3d667a4db00b491af35887022e9197bb244705bde', owner: '0xcd0247d0b67e53dde69b285e7a748e3dc390e8a5244eb9dd9c5c53d95e4cf0aa', type: '0x0868b71c0cba55bf0faf6c40df8c179c67a4d0ba0e79965b68b3d72d7dfbf666::position::Position', coin_type_a: '0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdt::USDT', coin_type_b: '0588cff9a50e0eaf4cd50d337c1a36570bc1517793fd3303e1513e8ad4d2aa96::usdc::USDC', liquidity: '0', tick_lower_index: -2, tick_upper_index: 2, index: '22', pool: '0x83c101a55563b037f4cd25e5b326b26ae6537dc8048004c1408079f7578dd160', reward_amount_owed_0: '0', reward_amount_owed_1: '0', reward_amount_owed_2: '0', reward_growth_inside_0: '0', reward_growth_inside_1: '0', reward_growth_inside_2: '0', fee_growth_inside_a: '0', fee_owed_a: '0', fee_growth_inside_b: '0', fee_owed_b: '0', position_status: 'Exists' } */ [](#id-4.-batch-get-position-fees) 4\. Batch get position fees ------------------------------------------------------------------- use `sdk.Position.batchFetchPositionFees()` method. #### [](#function-input-params-3) Function input params * positionIDs: An array of position ID. #### [](#example-3) Example Copy async function batchFetchPositionFees() { const positionIDs = [\ '0xf10d37cc00bcd60f85cef3fe473ea979e3f7f3631d522618e80c876b349e56bc',\ '0xfbf94213d59d285f66bacdb3d667a4db00b491af35887022e9197bb244705bde',\ ] const fees = await TestnetSDK.Position.batchFetchPositionFees(positionIDs) console.log('batch fetch position fees', fees) } [PreviousGet clmm pools](/cetus-developer-docs/developer/via-sdk/features-available/get-clmm-pools) [NextGet reward](/cetus-developer-docs/developer/via-sdk/features-available/get-reward) Last updated 2 months ago 💻 --- # Partner swap | Cetus Developer Docs [](#partner) Partner ------------------------- We offer a partner function. When you utilize the standard swap method, we will allocate the agreed-upon share to the partner. But, because of sui contract limitations, partner doesn't work in the latest smart router function with split order or integrate other pools like `deepbook`. [](#partner-accountcap) Partner AccountCap ----------------------------------------------- Only verified account are eligible to collect partner ref fees. When creating a partner, we generate an object **partner AccountCap**(you can see it in your NFT list). Only accounts that possess the AccountCap are able to claim the fees. [](#claim-ref-fee) Claim Ref Fee ------------------------------------- We provider one function `**sdk.Pool.claimPartnerRefFeePayload()**`to check ref fee. #### [](#function-input-params) Function input params _Please refer to the original function for specific parameter types._ * `**partnerCap**`: The object id about partner cap. * `**partner**`: The object id about partner. * `**coinType:**` The coin type abount fee coin type. You can obtain the referral fee using [this specified method.](/cetus-developer-docs/developer/via-sdk/features-available/partner-swap#check-ref-fee-of-partner) #### [](#example) Example Copy const partnerCap = '0x...' const partner = '0x...' const coinType = '0x...::...::....' const claimRefFeePayload = await sdk.Pool.claimPartnerRefFeePayload(partnerCap, partner, coinType) const transferTxn = await sdk.fullClient.sendTransaction(buildTestAccount(), claimRefFeePayload) console.log('doCreatPool: ', JSON.stringify(transferTxn)) [](#check-ref-fee-of-partner) Check ref fee of partner ----------------------------------------------------------- We provider one function `sdk.Pool.getPartnerRefFeeAmount()` to check ref fee. #### [](#function-input-params-1) Function input params _Please refer to the original function for specific parameter types._ * `**partnerID**`: The object id about partner. #### [](#example-1) Example Copy import BN from 'bn.js' import { initCetusSDK } from '@cetusprotocol/cetus-sui-clmm-sdk' const sdk = initCetusSDK({ network: 'mainnet' }) const partnerID = '0x...' const refFee = await sdk.Pool.getPartnerRefFeeAmount(partnerID) console.log('ref fee:', refFee) [](#interested-in-partner-swap-submit-a-request-from-here) **Interested in Partner Swap? Submit a request from here:** --------------------------------------------------------------------------------------------------------------------------- [https://4bx69zjogri.typeform.com/to/UUETIX2f](https://4bx69zjogri.typeform.com/to/UUETIX2f) [PreviousSwap](/cetus-developer-docs/developer/via-sdk/features-available/swap) [NextSmart router v1](/cetus-developer-docs/developer/via-sdk/features-available/smart-router-v1) Last updated 1 month ago --- # Fee | Cetus Developer Docs [](#how-to-calculate-fee-rate) How to calculate fee rate? -------------------------------------------------------------- Fee means the coin used to pay the protocol fee rate during the transaction differs from the gas consumed by the execution of the smart contract. Different pools has different fee rate. Each tick spacing corresponds to a specific fee rate. tick spacing fee rate 2 0.0001 10 0.0005 60 0.0025 200 0.01 1. For a single pathway, the fee is equal to the input amount multiplied by the fee rate. 2. In the case of multiple pathways or paths involving intermediary coins, we need to calculate the input amount multiplied by the fee rate for each individual swap. Then, convert all these amounts to the corresponding quantity in the input coin and sum them up. In SDK, we provide `sdk.Swap.calculateSwapFee()` method. #### [](#example) Example Copy const res = await sdk.RouterV2.getBestRouter(USDT, USDC, 100000000, true, 5, '', undefined, true, false) const fee = sdk.Swap.calculateSwapFee(res.result.splitPaths) console.log('fee: ', fee) [PreviousMinimum received & Maximum sold](/cetus-developer-docs/developer/via-sdk/features-available/minimum-received-and-maximum-sold) [NextLiquidity and coin amounts calculation](/cetus-developer-docs/developer/via-sdk/features-available/liquidity-and-coin-amounts-calculation) Last updated 1 year ago 💻 --- # Changelog | Cetus Developer Docs [PreviousPrice, tick index and sqrt price correlation calculation](/cetus-developer-docs/developer/via-sdk/features-available/price-tick-index-and-sqrt-price-correlation-calculation) [Nextvia Contract](/cetus-developer-docs/developer/via-contract) Last updated 6 days ago In both testnet and mainnet, we have set up default contract addresses. To integrate these changes, simply upgrade the `cetus-sui-clmm-sdk` package to version `**v5.3.4**`. Then, replace your current Cetus SDK initialization method with [`src/config/initCetusSDK`](/cetus-developer-docs/developer/via-sdk/prerequisites#setting-up-configuration) . More details can refer to [via SDK](/cetus-developer-docs/developer/via-sdk) . [](#cetus-sui-clmm-sdk-v5.3.4) cetus-sui-clmm-sdk v5.3.4 ------------------------------------------------------------- * Optimize `sdk.Pool.getPoolByCoins` method to support specifying the search for a specific fee rate. * * * [](#cetus-sui-clmm-sdk-v5.3.0) cetus-sui-clmm-sdk v5.3.0 ------------------------------------------------------------- * Upgrade clmm contract to package verison 10 * * * [](#cetus-sui-clmm-sdk-v5.2.0) cetus-sui-clmm-sdk v5.2.0 ------------------------------------------------------------- * Optimize build coin method. * * * [](#cetus-sui-clmm-sdk-v5.1.11) cetus-sui-clmm-sdk v5.1.11 --------------------------------------------------------------- * Update the method in clmm sdk for getting pool by coin types. 💻 [#clmm-version-10](/cetus-developer-docs/developer/via-contract/changelog#clmm-version-10) --- # Create clmm pool | Cetus Developer Docs Everyone can create cetus clmm pools directly. [](#id-1.-create-a-clmm-pool-with-some-initial-liquidity-to-be-added) 1\. Create a clmm pool with some initial liquidity to be added ----------------------------------------------------------------------------------------------------------------------------------------- #### [](#sdk.pool.createpooltransactionpayload) sdk.Pool.createPoolTransactionPayload() #### [](#function-input-params) Function input params _Please refer to the original function for specific parameter types._ * `**tick_spacing**`: tick spacing will affect price precision. Now mainnet exist some different type tick\_spacing, they correspond to different fee rates. tick spacing fee rate 2 0.0001 10 0.0005 20 0.001 60 0.0025 200 0.01 220 0.02 * `**initialize_sqrt_price**`: for computational convenience, we use fixed-point numbers to represent square root prices. Use the provided by the SDK transformation `price` to `sqrtPrice`: `TickMath.priceToSqrtPriceX64()`. * `**uri**`: the icon of pool, it's allows null. * `**coin_type_a**`: the coin type address about coinA. * `**coin_type_b**`: the coin type address about coinB. **How to determine coinTypeA and coinTypeB ?** 1. **Complete the Coin Type**: Before comparing, ensure that the coin type is complete. 2. **Character-by-Character Comparison**: Start from the first character and compare the characters of the two coins' coinType addresses one by one. 3. **ASCII Value Comparison**: When encountering differing characters, compare their ASCII values. The coin corresponding to the character with the larger ASCII value is considered "coin a". **Example 1**: * **coinTypeA**:`0x6864a6f921804860930db6ddbe2e16acdf8504495ea7481637a1c8b9a8fe54b::cetus::CETUS` * **coinTypeB**:`0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI` **Example 2**: * **coinTypeA**:`0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC` * **coinTypeB**:`0xc060006111016b8a020ad5b33834984a437aaa7d3c74c18e09a95d48aceab08c::coin::COIN` #### [](#example) Example * `**amount_a**`: the amount about coin A, which used to add liquidity. * `**amount_b**`: the amount about coin B, which used to add liquidity. _Notice: amount a and b was calculated by_ `_ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()_`_, it will affected by selected tick interval、amount about one fixed coin(coinA or coinB)、current sqrt price of pool and allowed price slippage. You can see the usage in the next example._ * `**fix_amount_a**`: `true` means fixed coinA amount, `false` means fixed coinB amount. * `**tick_lower**`: Represents the index of the lower tick boundary. * `**tick_upper**`: Represents the index of the upper tick boundary. * The tick index must be an integer multiple of `tickSpacing`. If the provided parameter is not a multiple of `tickSpacing`, the contract will throw an error. * \-443636 < `tickLowerIndex` < currentTickIndex<`tickUpperIndex` < 443636, 443636 is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format. * Currently, creating a pool requires adding bidirectional liquidity. * `**metadataA:**` The coin metadata id of the coin a. * `**metadataB:**` The coin metadata id of the coin b. #### [](#example-1) Example Copy import BN from 'bn.js' import { ClmmPoolUtil, initCetusSDK, TickMath } from '@cetusprotocol/cetus-sui-clmm-sdk' import { SuiClient } from '@mysten/sui/client' const sdk = initCetusSDK({network: 'mainnet'}) const signer = ... // set keypair sdk.senderAddress = signer.getPublicKey().toSuiAddress() // set sdk.senderAddress // initialize sqrt_price const initialize_sqrt_price = TickMath.priceToSqrtPriceX64(d(1.2),6,6).toString() const tick_spacing = 2 const current_tick_index = TickMath.sqrtPriceX64ToTickIndex(new BN(initialize_sqrt_price)) // build tick range const tick_lower = TickMath.getPrevInitializableTickIndex(new BN(current_tick_index).toNumber() , new BN(tick_spacing).toNumber()) const tick_upper = TickMath.getNextInitializableTickIndex(new BN(current_tick_index).toNumber() , new BN(tick_spacing).toNumber()) // input token amount const fix_coin_amount = new BN(200) // input token amount is token a const fix_amount_a = true // slippage value 0.05 means 5% const slippage = 0.05 const cur_sqrt_price = new BN(initialize_sqrt_price) // Estimate liquidity and token amount from one amounts const liquidityInput = ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts( lowerTick, upperTick, fix_coin_amount, fix_amount_a, true, slippage, cur_sqrt_price ) // Estimate token a and token b amount const amount_a = fix_amount_a ? fix_coin_amount.toNumber() : liquidityInput.tokenMaxA.toNumber() const amount_b = fix_amount_a ? liquidityInput.tokenMaxB.toNumber() : fix_coin_amount.toNumber() const coinTypeA = '0x3cfe7b9f6106808a8178ebd2d5ae6656cd0ccec15d33e63fd857c180bde8da75::coin:CetusUSDT' const coinTypeB = '0x3cfe7b9f6106808a8178ebd2d5ae6656cd0ccec15d33e63fd857c180bde8da75::coin::CetusUSDC' const coinMetadataAID = await suiClient.getCoinMetadata({coinType: coinTypeA}).id const coinMetadataBID = await suiClient.getCoinMetadata({coinType: coinTypeB}).id // build creatPoolPayload Payload const creatPoolPayload = sdk.Pool.createPoolTransactionPayload({ coinTypeA, coinTypeB, tick_spacing: tick_spacing, initialize_sqrt_price: initialize_sqrt_price, uri: '', amount_a, amount_b, fix_amount_a, tick_lower, tick_upper, metadata_a: coinMetadataAID, metadata_b: coinMetadataBID, }) const res = await sendTransaction(signer, creatPoolTransactionPayload, true) [PreviousGet ticks](/cetus-developer-docs/developer/via-sdk/features-available/get-ticks) [NextOpen position](/cetus-developer-docs/developer/via-sdk/features-available/open-position) Last updated 1 month ago 💻 --- # Price impact | Cetus Developer Docs [](#how-to-calculate-price-impact) How to calculate price impact? ---------------------------------------------------------------------- Price impact means the variation rate between the prices of the two coins in actual transactions and the pre-calculated prices. The SDK providers the `sdk.Swap.calculateSwapPriceImpact` method to calculated it. #### [](#example) Example Copy const res = await sdk.RouterV2.getBestRouter(USDT, USDC, 100000000, true, 5, '', undefined, true, false) const priceImpact = sdk.Swap.calculateSwapPriceImpact(res.result.splitPaths) console.log('priceImpact: ', priceImpact ) [PreviousSmart router v2](/cetus-developer-docs/developer/via-sdk/features-available/smart-router-v2) [NextMinimum received & Maximum sold](/cetus-developer-docs/developer/via-sdk/features-available/minimum-received-and-maximum-sold) Last updated 1 year ago 💻 --- # Collect fees | Cetus Developer Docs When you add liquidity within a valid price range, all transaction fees generated within this range will be distributed based on the proportional share of effective liquidity from all positions within the current range. If you intend to harvest transaction fees separately, please follow the method below. #### [](#function-input-params) Function input params _Please refer to the original function for specific parameter types._ * `**poolID**`: The object id about which pool you want to operation. * `**posID**`: The object id about position. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. #### [](#example) Example Copy const sendKeypair = buildTestAccount() // Fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // Fetch position data const position = await sdk.Position.getPosition(position_object_id) // build collect fee Payload const removeLiquidityPayload = (await sdk.Position.collectFeeTransactionPayload( { pool_id: pool.poolAddress, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, pos_id: position.position_object_id, }, true )) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair,collectFeeTransactionPayload) console.log('collect_fee: ', transferTxn) [PreviousClose position](/cetus-developer-docs/developer/via-sdk/features-available/close-position) [NextCollect rewards](/cetus-developer-docs/developer/via-sdk/features-available/collect-rewards) Last updated 8 months ago 💻 --- # Price, tick index and sqrt price correlation calculation | Cetus Developer Docs [](#whats-difference-between-price-tick-index-and-sqrt-price) What's difference between price, tick index and sqrt price? ------------------------------------------------------------------------------------------------------------------------------ Concept Definition Features Application **Price** Token exchange ratio (e.g., `token1/token0`) Continuous value, updates in real-time Directly determines trading rates **Tick Index** Discretized price interval index Spacing determined by fee tiers Manages liquidity distribution ranges **Sqrt Price** Square root of price Stored as fixed-point numbers (e.g., `sqrtPriceX64`) Simplifies on-chain calculations, improves efficiency **Notes:** 1. **Price**: Represents the real-time ratio between two tokens (e.g., ETH/USDC). 2. **Tick Index**: * Derived from `P = 1.0001^i`, where `i` is the Tick Index. * Liquidity can only be provided at discrete Ticks (e.g., multiples of 10). 3. **Sqrt Price**: * Used for computational efficiency (avoids floating-point operations). * In Uniswap V3, stored as `sqrtPriceX64` (Q64 fixed-point format). [](#id-1.-tick-index-to-price) 1\. Tick index to price ----------------------------------------------------------- when you want to open position, you dont know how to set your tick\_lower and tick\_upper. use `/src/math/tick.ts TickMath.`tickIndexToPrice`()` Copy import { TickMath } from '@cetusprotocol/cetus-sui-clmm-sdk' // decimalsA and decimalsB means the decimal of coinA and coinB const price = TickMath.tickIndexToPrice(tickIndex, decimalsA, decimalsB) [](#id-2.price-to-tick-index) 2.Price to tick index -------------------------------------------------------- use `/src/math/tick.ts TickMath.priceToTickIndex()` Copy import { TickMath } from '@cetusprotocol/cetus-sui-clmm-sdk' // decimalsA and decimalsB means the decimal of coinA and coinB const tickIndex = TickMath.priceToTickIndex(price, decimalsA, decimalsB) [](#id-3.-tick-index-to-sqrt-price-x64) 3\. Tick index to sqrt price x64 ----------------------------------------------------------------------------- use `/src/math/tick.ts TickMath.tickIndexToSqrtPriceX64()` Copy import { TickMath } from '@cetusprotocol/cetus-sui-clmm-sdk' const sqrtPriceX64 = TickMath.tickIndexToSqrtPriceX64(tickIndex) [](#id-4.-sqrt-price-x64-to-tick-index) 4\. Sqrt price x64 to tick index ----------------------------------------------------------------------------- use `/src/math/tick.ts TickMath.sqrtPriceToTickIndex()` Copy import { TickMath } from '@cetusprotocol/cetus-sui-clmm-sdk' const tickIndex = TickMath.sqrtPriceX64ToTickIndex(sqrtPriceX64) [](#id-5.-price-to-sqrt-price) 5\. Price to sqrt price ----------------------------------------------------------- use `/src/math/tick.ts TickMath.`priceToSqrtPriceX64`()` Copy import { TickMath } from '@cetusprotocol/cetus-sui-clmm-sdk' // decimalsA and decimalsB means the decimal of coinA and coinB const sqrtPriceX64 = TickMath.priceToSqrtPriceX64(price, decimalsA, decimalsB) [](#id-6.-sqrt-price-to-price) 6\. Sqrt price to price ----------------------------------------------------------- use `/src/math/tick.ts TickMath.sqrtPriceX64ToPrice()` Copy import { TickMath } from '@cetusprotocol/cetus-sui-clmm-sdk' // decimalsA and decimalsB means the decimal of coinA and coinB const price = TickMath.sqrtPriceX64ToPrice(sqrtPriceX64, decimalsA, decimalsB) [](#id-7.-convert-the-tick-index-from-i32-to-u32) 7\. Convert the tick index from i32 to u32 ------------------------------------------------------------------------------------------------- In the TS SDK, for easier display, we will convert u32 to i32. If you need to call the contract directly, you can also use the method below to convert i32 to u32. Copy import { asUintN } from '@cetusprotocol/cetus-sui-clmm-sdk' const tickLowerI32 = -100 const tickLowerU32 = asUintN(BigInt(tickLowerI32)).toString() const tickUpperI32 = 100 const tickUpperU32 = asUintN(BigInt(tickUpperI32)).toString() [PreviousAPR correlation calculation](/cetus-developer-docs/developer/via-sdk/features-available/apr-correlation-calculation) [NextChangelog](/cetus-developer-docs/developer/via-sdk/changelog) Last updated 5 days ago --- # Get ticks | Cetus Developer Docs [](#id-1.-batch-get-ticks-by-pool-id) 1\. Batch get ticks by pool ID ------------------------------------------------------------------------- use `SDK.Pool.fetchTicks()` method #### [](#function-input-params) Function input params * poolID: The pool object ID. * coinTypeA: Coin A type. * coinTypeB: Coin B type. #### [](#example) Example Copy async function betchGetTicksByPoolID() { const tickdatas = await TestnetSDK.Pool.fetchTicks({ pool_id: '0xbed3136f15b0ea649fb94bcdf9d3728fb82ba1c3e189bf6062d78ff547850054', coinTypeA: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdt::USDT', coinTypeB: '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::cetus::CETUS', }) console.log('fetchTicks: ', tickdatas) } // betchGetTicksByPoolID() /* fetchTicks: [\ {\ objectId: '',\ index: -443636,\ sqrtPrice: ,\ liquidityNet: ,\ liquidityGross: ,\ feeGrowthOutsideA: ,\ feeGrowthOutsideB: ,\ rewardersGrowthOutside: []\ },\ {\ objectId: '',\ index: -5630,\ sqrtPrice: ,\ liquidityNet: ,\ liquidityGross: ,\ feeGrowthOutsideA: ,\ feeGrowthOutsideB: ,\ rewardersGrowthOutside: [\ '493908213970774732607273',\ '1536244159578954174',\ '1228332157000808067268'\ ]\ },\ ...\ ] */ [](#id-2.-batch-get-ticks-by-tickhandle) 2\. Batch get ticks by tickHandle ------------------------------------------------------------------------------- use `SDK.Pool.fetchTicksByRpc()` method #### [](#function-input-params-1) Function input params * tickHandle: The tick handle of pool. #### [](#example-1) Example Copy async function betchFetchTicksByRpc() { const pool = await TestnetSDK.Pool.getPool('0x6fd4915e6d8d3e2ba6d81787046eb948ae36fdfc75dad2e24f0d4aaa2417a416') const tickdatas = await TestnetSDK.Pool.fetchTicksByRpc(pool.ticks_handle) console.log('tick data:', tickdatas) } // betchFetchTicksByRpc() /* [\ {\ objectId: '0x012cc2b51309c25256a4249f586c5b997bdef52b4650c975988ae951083f3d07',\ index: 120,\ sqrtPrice: ,\ liquidityNet: ,\ liquidityGross: ,\ feeGrowthOutsideA: ,\ feeGrowthOutsideB: ,\ rewardersGrowthOutside: [ '0' ]\ },\ {\ objectId: '0x02d64aaa0665387c739a3488c57cff9c306a13e81fb340b0909d6e1f3339018d',\ index: 186,\ sqrtPrice: ,\ liquidityNet: ,\ liquidityGross: ,\ feeGrowthOutsideA: ,\ feeGrowthOutsideB: ,\ rewardersGrowthOutside: [ '0' ]\ },\ ...\ ] */ [PreviousGet reward](/cetus-developer-docs/developer/via-sdk/features-available/get-reward) [NextCreate clmm pool](/cetus-developer-docs/developer/via-sdk/features-available/create-clmm-pool) Last updated 2 months ago 💻 --- # Open position | Cetus Developer Docs Before you want to deposit liquidity, you need to choose an appropriate price range (corresponding to the tick range) to open a position. There are two situations: * open a position only * open positon and add liquidity **(recommended)** In most cases, opening a position and adding liquidity are supposed to be done simultaneously. [](#id-1.-open-a-position-only) 1\. Open a position only ------------------------------------------------------------- Use `sdk.Position.openPositionTransactionPayload()` method. #### [](#function-input-params) Function input params _Please refer to the original function for specific parameter types._ * `**poolID**`: The object id about which pool you want to operation. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**tickLower**`: Represents the index of the lower tick boundary. * `**tickUpper**`: Represents the index of the upper tick boundary. * The tick index must be an integer multiple of `tickSpacing`. If the provided parameter is not a multiple of `tickSpacing`, the contract will throw an error. * \-443636 < `tickLowerIndex` < `tickUpperIndex` < 443636, 443636 is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format. * If you know price range, then you can use `TickMath.priceToTickIndex()` to transform real price to tick index. * You can just open one position near the current price of the pool, use `TickMath.getPrevInitializableTickIndex()` and `TickMath.getNextInitializableTickIndex()` to find the next initialized tick. * If you want to add global liquidity, you can set `tickLowerIndex` = - 443636 + (443636 % tick\_spacing), `tickUpperIndex` = 443636 - (443636 % tick\_spacing) #### [](#example) Example: Copy const sendKeypair = buildTestAccount() // fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // build tick range const lowerTick = TickMath.getPrevInitializableTickIndex( new BN(pool.current_tick_index).toNumber(), new BN(pool.tickSpacing).toNumber() ) const upperTick = TickMath.getNextInitializableTickIndex( new BN(pool.current_tick_index).toNumber(), new BN(pool.tickSpacing).toNumber() ) // build open position payload const openPositionTransactionPayload = sdk.Position.openPositionTransactionPayload({ coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, tick_lower: lowerTick.toString(), tick_upper: upperTick.toString(), pool_id: pool.poolAddress, }) console.log('openPositionTransactionPayload: ', openPositionTransactionPayload) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair,openPositionTransactionPayload) [](#id-2.-open-position-with-add-liquidity) 2\. Open position with add liquidity ------------------------------------------------------------------------------------- Use `sdk.Position.createAddLiquidityFixTokenPayload()` method. #### [](#function-input-params-1) Function input params _Please refer to the original function for specific parameter types._ * `**poolID**`: The object id about which pool you want to operation. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**tickLower**`: Represents the index of the lower tick boundary. * `**tickUpper**`: Represents the index of the upper tick boundary. * The tick index must be an integer multiple of `tickSpacing`. If the provided parameter is not a multiple of `tickSpacing`, the contract will throw an error. * \-443636 < `tickLowerIndex` < `tickUpperIndex` < 443636, 443636 is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format. * If you know price range, then you can use `TickMath.priceToTickIndex()` to transform real price to tick index. * You can just open one position near the current price of the pool, use `TickMath.getPrevInitializableTickIndex()` and `TickMath.getNextInitializableTickIndex()` to find the next initialized tick. * If you want to add global liquidity, you can set `tickLowerIndex` = - 443636 + (443636 % tick\_spacing), `tickUpperIndex` = 443636 - (443636 % tick\_spacing) * `**isOpen**`: `true` means if first add liquidity, so needs open one position. * `**posID**`: The object id about position. * `**fixAmountA**`: `true` means fixed coinA amount, `false` means fixed coinB amount * `**amountA**`: If fixed amount A, you must set `amountA`, `amountB` will be auto calculated by `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()`. * `**amountB**`: If fixed amount B, you must set `amountB`, `amountA` will be auto calculated by `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()`. `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()` calculate result means when fixed one coin amount, another coin amount will change because of pool price change. so it will calculated based on the current pool price and processed with slippage. * `**slippage**`: Price slippage point. * `**collectFee**`: If you already has one position, you can select collect fees while adding liquidity. * `**rewarderCoinTypes**`: If these not empty, it will collect rewarder in this position, if you already open the position. #### [](#example-1) Example Copy const poolObjectId = '0xcf994611fd4c48e277ce3ffd4d4364c914af2c3cbb05f7bf6facd371de688630' // TokensMapping.USDT_USDC_LP.poolObjectIds[0] const pool = await buildTestPool(sdk, poolObjectId) const lowerTick = TickMath.getPrevInitializableTickIndex( new BN(pool.current_tick_index).toNumber(), new BN(pool.tickSpacing).toNumber() ) const upperTick = TickMath.getNextInitializableTickIndex( new BN(pool.current_tick_index).toNumber(), new BN(pool.tickSpacing).toNumber() ) const coinAmount = new BN(100) const fix_amount_a = true const slippage = 0.01 const curSqrtPrice = new BN(pool.current_sqrt_price) const liquidityInput = ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts( lowerTick, upperTick, coinAmount, fix_amount_a, true, slippage, curSqrtPrice ) const amount_a = fix_amount_a ? coinAmount.toNumber() : liquidityInput.tokenMaxA.toNumber() const amount_b = fix_amount_a ? liquidityInput.tokenMaxB.toNumber() : coinAmount.toNumber() console.log('amount: ', { amount_a, amount_b }) const addLiquidityPayloadParams: AddLiquidityFixTokenParams = { coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, pool_id: pool.poolAddress, tick_lower: lowerTick.toString(), tick_upper: upperTick.toString(), fix_amount_a, amount_a, amount_b, slippage, is_open: true, rewarder_coin_types: [], collect_fee: false, pos_id: '', } const createAddLiquidityTransactionPayload = await sdk.Position.createAddLiquidityFixTokenPayload(addLiquidityPayloadParams, { slippage: slippage, curSqrtPrice: curSqrtPrice, }) printTransaction(createAddLiquidityTransactionPayload) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair, createAddLiquidityTransactionPayload) console.log('open_and_add_liquidity_fix_token: ', transferTxn) [PreviousCreate clmm pool](/cetus-developer-docs/developer/via-sdk/features-available/create-clmm-pool) [NextAdd liquidity](/cetus-developer-docs/developer/via-sdk/features-available/add-liquidity) Last updated 1 year ago 💻 --- # Getting Started | Cetus Developer Docs [](#how-to-depend-on-this-service) How to depend on this service? ---------------------------------------------------------------------- #### [](#dependencies) Dependencies MainnetTestnet Copy CetusClmm = { git = "https://github.com/CetusProtocol/cetus-clmm-interface.git", subdir = "sui/cetus_clmm", rev = "mainnet-v1.26.0", override = true } Copy CetusClmm = { git = "https://github.com/CetusProtocol/cetus-clmm-interface.git", subdir = "sui/cetus_clmm", rev = "testnet-v1.26.0", override = true } #### [](#example) Example MainnetTestnet Copy [package] name= "cetus_example" version = "0.0.1" [dependencies] CetusClmm = { git = "https://github.com/CetusProtocol/cetus-clmm-interface.git", subdir = "sui/cetus_clmm", rev = "mainnet-v1.26.0" } [address] cetus_example = "0x0" // don't need to define cetus_clmm duplicate Copy [package] name= "cetus_example" version = "0.0.1" [dependencies] CetusClmm = { git = "https://github.com/CetusProtocol/cetus-clmm-interface.git", subdir = "sui/cetus_clmm", rev = "testnet-v1.26.0", override = true } [address] cetus_example = "0x0" // don't need to define cetus_clmm duplicate [](#how-to-build-and-publish) How to build and publish? ------------------------------------------------------------ Cetus clmm interface is not complete in terms of code base (only function definition is provided), so it will get failed when sui client checks its code version. However, this does not affect its actual functionality. Therefore, we need to add a `--dependencies-are-root` during the build and publish. ### [](#global-config-id) Global config id MainnetTestnet Global Config ID: Copy 0xdaa46292632c3c4d8f31f23ea0f9b36a28ff3677e9684980e4438403a67a3d8f Global Config ID: Copy 0x9774e359588ead122af1c7e7f64e14ade261cfeecdb5d0eb4a5b3b4c8ab8bd3e [Previousvia Contract](/cetus-developer-docs/developer/via-contract) [NextData Structure](/cetus-developer-docs/developer/via-contract/data-structure) Last updated 24 days ago --- # Add liquidity | Cetus Developer Docs Once you have set a suitable tick range, you can proceed to add liquidity to this position. The quantity composition of tokens you need to add is affected by the current price of the pool and the tick interval you have chosen. There are two situations: * add liquidity with a specified liquidity value * add liquidity with fixed coin amount. [](#id-1.-add-liquidity-with-a-specified-liquidity-value) 1\. Add liquidity with a specified liquidity value ----------------------------------------------------------------------------------------------------------------- use `sdk.Position.createAddLiquidityPayload()` method. #### [](#function-input-params) Function input params _Please refer to the original function for specific parameter types._ * `**poolID**`: The object id about which pool you want to operation. * `**posID**`: The object id about position. * `**maxAmountA**`: The max limit about used coin a amount. * `**maxAmountB**`: The max limit about used coin b amount. * `**deltaLiquidity**`: The actual change in liquidity that has been added. > how to calculate `**deltaLiquidity**` `**maxAmountA**` and `**maxAmountB**` ? > > 1. you can set fixed two coin amount you want to use. > > 2. use `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()` to calculated the `delataLiquidity`. > > 3. Apply price slippage adjustment to the two coin amounts(`max_amount_a` and `max_amount_b`) calculated above by method `adjustForCoinSlippage`. > _Notice_: how to calculate `**deltaLiquidity**` `**maxAmountA**` and `**maxAmountB**` ? * `**tickLower**`: Represents the index of the lower tick boundary. * `**tickUpper**`: Represents the index of the upper tick boundary. * `**collectFee**`: If you already has one position, you can select collect fees while adding liquidity. * `**rewarderCoinTypes**`: If these not empty, it will collect rewarder in this position, if you already open the position. #### [](#example) Example Copy const pool = await buildTestPool(sdk, TokensMapping.USDT_USDC_LP.poolObjectIds[0]) const curSqrtPrice = new BN(pool.current_sqrt_price) // ===>tick_uppe const tick_lower_index = -304 const tick_upper_index = 552 const slippageTolerance = new Percentage(new BN(5), new BN(100)) const totalAmount = '18.73' const tokenPriceA = '1.000625867190606471' const tokenPriceB = '1' const coinAmounts = ClmmPoolUtil.estCoinAmountsFromTotalAmount( tick_lower_index, tick_upper_index, curSqrtPrice, totalAmount, tokenPriceA, tokenPriceB ) console.log('coinAmounts: ', coinAmounts) const amountA = toDecimalsAmount(coinAmounts.amountA.toFixed(6, Decimal.ROUND_UP).toString(), 6) const amountB = toDecimalsAmount(coinAmounts.amountB.toFixed(6, Decimal.ROUND_UP).toString(), 6) const tokenAmounts = { coinA: new BN(amountA), coinB: new BN(amountB), } const liquidity = ClmmPoolUtil.estimateLiquidityFromcoinAmounts(curSqrtPrice, tick_lower_index, tick_upper_index, tokenAmounts) console.log('liquidity: ', liquidity.toString()) const { tokenMaxA, tokenMaxB } = adjustForCoinSlippage(tokenAmounts, slippageTolerance, true) const addLiquidityPayloadParams: AddLiquidityParams = { coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, pool_id: pool.poolAddress, tick_lower: tick_lower_index.toString(), tick_upper: tick_upper_index.toString(), delta_liquidity: liquidity.toString(), max_amount_a: tokenMaxA.toString(), max_amount_b: tokenMaxB.toString(), pos_id: '', rewarder_coin_types: [], collect_fee: false, } const payload = await sdk.Position.createAddLiquidityPayload(addLiquidityPayloadParams) printTransaction(payload) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair, payload) console.log('createAddLiquidityPayload: ', transferTxn) [](#id-2.-add-liquidity-with-a-fixed-coin-amount) 2\. Add liquidity with a fixed coin amount ------------------------------------------------------------------------------------------------- This function is the same as open position and add liquidity with fixed coin amount. #### [](#function-input-params-1) Function input params _Please refer to the original function for specific parameter types._ * `**poolID**`: The object id about which pool you want to operation. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**tickLower**`: Represents the index of the lower tick boundary. * `**tickUpper**`: Represents the index of the upper tick boundary. * The tick index must be an integer multiple of `tickSpacing`. If the provided parameter is not a multiple of `tickSpacing`, the contract will throw an error. * \-443636 < `tickLowerIndex` < `tickUpperIndex` < 443636, 443636 is a constant, derived from the maximum range representable by the Q32.62 fixed-point number format. * If you know price range, then you can use `TickMath.priceToTickIndex()` to transform real price to tick index. * You can just open one position near the current price of the pool, use `TickMath.getPrevInitializableTickIndex()` and `TickMath.getNextInitializableTickIndex()` to find the next initialized tick. * If you want to add global liquidity, you can set `tickLowerIndex` = - 443636 + (443636 % tick\_spacing), `tickUpperIndex` = 443636 - (443636 % tick\_spacing) * `**isOpen**`: `true` means if first add liquidity, so needs open one position. * `**posID**`: The object id about position. * `**fixAmountA**`: `true` means fixed coinA amount, `false` means fixed coinB amount * `**amountA**`: If fixed amount A, you must set `amount_a`, `amount_b` will be auto calculated by `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()`. * `**amountB**`: If fixed amount B, you must set `amount_b`, `amount_a` will be auto calculated by `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()`. _Notice_: `ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts()` calculate result means when fixed one coin amount, another coin amount will change because of pool price change. so it will calculated based on the current pool price and processed with slippage. * `**slippage**`: Price slippage point. * `**collectFee**`: If you already has one position, you can select collect fees while adding liquidity. * `**rewarderCoinTypes**`: If these not empty, it will collect rewarder in this position, if you already open the position. #### [](#example-1) Example Copy const poolObjectId = '0xcf994611fd4c48e277ce3ffd4d4364c914af2c3cbb05f7bf6facd371de688630' // TokensMapping.USDT_USDC_LP.poolObjectIds[0] const pool = await buildTestPool(sdk, poolObjectId) const lowerTick = TickMath.getPrevInitializableTickIndex( new BN(pool.current_tick_index).toNumber(), new BN(pool.tickSpacing).toNumber() ) const upperTick = TickMath.getNextInitializableTickIndex( new BN(pool.current_tick_index).toNumber(), new BN(pool.tickSpacing).toNumber() ) const coinAmount = new BN(100) const fix_amount_a = true const slippage = 0.01 const curSqrtPrice = new BN(pool.current_sqrt_price) const liquidityInput = ClmmPoolUtil.estLiquidityAndcoinAmountFromOneAmounts( lowerTick, upperTick, coinAmount, fix_amount_a, true, slippage, curSqrtPrice ) const amount_a = fix_amount_a ? coinAmount.toNumber() : liquidityInput.tokenMaxA.toNumber() const amount_b = fix_amount_a ? liquidityInput.tokenMaxB.toNumber() : coinAmount.toNumber() console.log('amount: ', { amount_a, amount_b }) const addLiquidityPayloadParams: AddLiquidityFixTokenParams = { coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, pool_id: pool.poolAddress, tick_lower: lowerTick.toString(), tick_upper: upperTick.toString(), fix_amount_a, amount_a, amount_b, slippage, is_open: true, rewarder_coin_types: [], collect_fee: false, pos_id: '', } const createAddLiquidityTransactionPayload = await sdk.Position.createAddLiquidityFixTokenPayload(addLiquidityPayloadParams, { slippage: slippage, curSqrtPrice: curSqrtPrice, }) printTransaction(createAddLiquidityTransactionPayload) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair, createAddLiquidityTransactionPayload) console.log('open_and_add_liquidity_fix_token: ', transferTxn) [PreviousOpen position](/cetus-developer-docs/developer/via-sdk/features-available/open-position) [NextRemove liquidity](/cetus-developer-docs/developer/via-sdk/features-available/remove-liquidity) Last updated 1 year ago 💻 --- # Swap | Cetus Developer Docs [](#swap) Swap ------------------- Swaps typically occur in two steps: * the first step involves pre-calculating the potential result of the current transaction; * the second step is to set the slippage based on the pre-calculated results, followed by executing the transaction. After pre-calcualting then you can do swap via: * swap * [partner swap](/cetus-developer-docs/developer/via-sdk/features-available/partner-swap) [](#swap-after-preswap) Swap after preswap ----------------------------------------------- After pre-calcualting then swap. [For a more detailed understanding of the pre-swap process and its intricacies, additional information is available here.](/cetus-developer-docs/developer/via-sdk/features-available/preswap) #### [](#function-input-param) Function input param _Please refer to the original function for specific parameter types._ * `**poolID**`: pool object id, you can get it by pre-calcualting. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**a2b**`: swap direction, `true` means swap from coinA to coinB, `false` means swap from coinB to CoinA. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**amount**`: the amount of input (`byAmountIn` = `true`) or output (`byAmountIn` = `false`). * `**amountLimit**`: the amount limit of coin what you get. There are two scenarios in amount limit, when by\_amount\_in equals true, amount limit means minimum number of outputs required to be obtained, when by\_amount\_in equals false, it means maximum number of input coin. * `**partner**`: The partner address. If you do not have a partner, simply leave the partner field unset. _Notice_: * This is the amount out of result after slippage adjustment. Use `adjustForSlippage` to calculate the limit of amount out. * If you set amount limit equal 0, when you trade during extremely volatile price fluctuations, you might end up with a very small trading outcome. The `amountLimit` will help prevent your assets from incurring losses. * You can get more details in these [Partner swap](/cetus-developer-docs/developer/via-sdk/features-available/partner-swap) parts. #### [](#example) Example Copy import BN from 'bn.js' import { adjustForSlippage, d, initCetusSDK, Percentage, TransactionUtil } from '@cetusprotocol/cetus-sui-clmm-sdk' const sdk = initCetusSDK({ network: 'mainnet' }) const sendKeypair = buildTestAccount() // Whether the swap direction is token a to token b const a2b = true // fix input token amount const coinAmount = new BN(120000) // input token amount is token a const byAmountIn = true // slippage value const slippage = Percentage.fromDecimal(d(5)) // Fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // Estimated amountIn amountOut fee const res: any = await sdk.Swap.preswap({ pool: pool, current_sqrt_price: pool.current_sqrt_price, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, decimalsA: 6, // coin a 's decimals decimalsB: 8, // coin b 's decimals a2b, by_amount_in, amount, }) const partner = '0x8e0b7668a79592f70fbfb1ae0aebaf9e2019a7049783b9a4b6fe7c6ae038b528' const toAmount = byAmountIn ? res.estimatedAmountOut : res.estimatedAmountIn const amountLimit = adjustForSlippage(toAmount, slippage, !byAmountIn) // build swap Payload const swapPayload = sdk.Swap.createSwapTransactionPayload( { pool_id: pool.poolAddress, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB a2b: a2b, by_amount_in: by_amount_in, amount: res.amount.toString(), amount_limit: amountLimit.toString(), swap_partner: partner, }, ) const swapTxn = await sdk.fullClient.sendTransaction(signer, swapPayload) [](#swap-without-transfer-coins) Swap without transfer coins ----------------------------------------------------------------- This methods support return two coins for user to build PTB. #### [](#function-input-param-1) Function input param _Please refer to the original function for specific parameter types._ * `**poolID**`: pool object id, you can get it by pre-calcualting. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**a2b**`: swap direction, `true` means swap from coinA to coinB, `false` means swap from coinB to CoinA. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**amount**`: the amount of input (`byAmountIn` = `true`) or output (`byAmountIn` = `false`). * `**amountLimit**`: the amount limit of coin what you get. There are two scenarios in amount limit, when by\_amount\_in equals true, amount limit means minimum number of outputs required to be obtained, when by\_amount\_in equals false, it means maximum number of input coin. * `**partner**`: The partner address. If you do not have a partner, simply leave the partner field unset. _Notice_: * This is the amount out of result after slippage adjustment. Use `adjustForSlippage` to calculate the limit of amount out. * If you set amount limit equal 0, when you trade during extremely volatile price fluctuations, you might end up with a very small trading outcome. The `amountLimit` will help prevent your assets from incurring losses. * You can get more details in these [Partner swap](/cetus-developer-docs/developer/via-sdk/features-available/partner-swap) parts. #### [](#example-1) Example Copy import BN from 'bn.js' import { adjustForSlippage, d, initCetusSDK, Percentage, TransactionUtil } from '@cetusprotocol/cetus-sui-clmm-sdk' const sdk = initCetusSDK({ network: 'mainnet' }) const sendKeypair = buildTestAccount() // Whether the swap direction is token a to token b const a2b = true // fix input token amount const coinAmount = new BN(120000) // input token amount is token a const byAmountIn = true // slippage value const slippage = Percentage.fromDecimal(d(5)) // Fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // Estimated amountIn amountOut fee const res: any = await sdk.Swap.preswap({ pool: pool, current_sqrt_price: pool.current_sqrt_price, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, decimalsA: 6, // coin a 's decimals decimalsB: 8, // coin b 's decimals a2b, by_amount_in, amount, }) const partner = '0x8e0b7668a79592f70fbfb1ae0aebaf9e2019a7049783b9a4b6fe7c6ae038b528' const toAmount = byAmountIn ? res.estimatedAmountOut : res.estimatedAmountIn const amountLimit = adjustForSlippage(toAmount, slippage, !byAmountIn) // build swap Tx const {swapTx, coinsAB} = sdk.Swap.createSwapTransactionWithoutTransferCoinsPayload( { pool_id: pool.poolAddress, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB a2b: a2b, by_amount_in: by_amount_in, amount: res.amount.toString(), amount_limit: amountLimit.toString(), swap_partner: partner, }, ) // transfer coin a and coin b swapTx.transferObjects(coins, tx.pure.address(recipient)) const transferTxn = await sdk.fullClient.sendTransaction(signer,swapPayload) console.log('swap: ', transferTxn) [PreviousPreswap](/cetus-developer-docs/developer/via-sdk/features-available/preswap) [NextPartner swap](/cetus-developer-docs/developer/via-sdk/features-available/partner-swap) Last updated 1 month ago 💻 --- # Liquidity and coin amounts calculation | Cetus Developer Docs [](#id-1.-liquidity-to-coinamount) 1\. Liquidity to CoinAmount ------------------------------------------------------------------- use `ClmmPoolUtil.getCoinAmountFromLiquidity` method. #### [](#example) Example this is an example shows how to calculate coin amounts about one position. Copy import BN from 'bn.js' import { TickMath, ClmmPoolUtil } from '@cetusprotocol/cetus-sui-clmm-sdk' const pool = await sdk.Pool.getPool(poolAddress) const position = await sdk.Position.getSimplePosition(positionAddress)\ const lowerSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_lower_index) const upperSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_upper_index) const liquidity = new BN(position.liquidity) const curSqrtPrice = new BN(pool.current_sqrt_price) const lowerSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_lower_index) const upperSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_upper_index) const amounts = ClmmPoolUtil.getCoinAmountFromLiquidity( liquidity, curSqrtPrice, lowerSqrtPrice, upperSqrtPrice, false ) const {coinA, coinB} = amounts [PreviousFee](/cetus-developer-docs/developer/via-sdk/features-available/fee) [NextAPR correlation calculation](/cetus-developer-docs/developer/via-sdk/features-available/apr-correlation-calculation) Last updated 25 days ago 💻 --- # Collect rewards | Cetus Developer Docs When you provide liquidity within a valid price range, when transactions occurring within this range, the rewards will be distributed every second based on the proportional share of effective liquidity from all positions within the current range. If you intend to harvest rewards separately, please follow the method below. #### [](#function-input-params) Function input params * `**poolID**`: The object id about which pool you want to operation. * `**posID**`: The object id about position. * `**rewarderCoinTypes**`: If these not empty, it will collect rewarders in this position, if you already open the position. You can even determine which types of rewards you want to harvest by specifying the coin types you pass. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**collectFee**`: you can select weather collect fees while adding liquidity. #### [](#example) Example Copy const sendKeypair = buildTestAccount() // Fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // Fetch all rewarder for position const rewards: any[] = await sdk.Rewarder.posRewardersAmount(pool.poolAddress, poolObjectId) const rewardCoinTypes = rewards.filter((item) => Number(item.amount_owed) > 0).map((item)=> item.coin_address) // build collect rewarder Payload const collectRewarderParams: CollectRewarderParams = { pool_id: pool.poolAddress, pos_id: poolObjectId, rewarder_coin_types: [ ...rewardCoinTypes], coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, collect_fee: false } const collectRewarderPayload = sdk.Rewarder.collectRewarderTransactionPayload(collectRewarderParams) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair,collectRewarderPayload) console.log('collect_fee: ', transferTxn) [PreviousCollect fees](/cetus-developer-docs/developer/via-sdk/features-available/collect-fees) [NextPreswap](/cetus-developer-docs/developer/via-sdk/features-available/preswap) Last updated 1 year ago 💻 --- # Preswap | Cetus Developer Docs This text describes two primary methods for performing a swap function, each with distinct steps and calculation methods. The first method involves initially obtaining tick data, followed by performing calculations locally. The second method involves conducting a simulated swap and then obtaining the resultant data through an event on Sui. There are three pre-calculation strategies for executing a swap: 1. Local Calculate * local calculate swap result: use `sdk.Swap.calculateRates()` 1. Simulate swap then get result * only calculate one pool swap result: use `sdk.Swap.preswap()`. * calculate multi pool at the same time, use `sdk.Swap.preSwapWithMultiPool()`. It will select one best pool to do swap. [](#local-calculate-swap-result) Local calculate swap result ----------------------------------------------------------------- This method need to get ticks data and pool object first. use `sdk.Swap.calculateRates` method. #### [](#function-input-param) Function input param _Please refer to the original function for specific parameter types._ * params: `CalculateRatesParams` object. * `**decimalsA**`: the decimal of coinA. * `**decimalsB**`: the decimal of coinB. * `**a2b**`: swap direction, `true` means swap from coinA to coinB, `false` means swap from coinB to CoinA. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**amount**`: the amount of input (`byAmountIn` = `true`) or output (`byAmountIn` = `false`). * `**swapTicks**`: the array of `**TickData**``,`[get them by `**sdk.Pool.fetchTicks()**`](/cetus-developer-docs/developer/via-sdk/features-available/get-ticks#id-1.-batch-retrieve-ticks-by-pool-id) . * `**pool**`: the `**pool**` object, [get it by `**sdk.Pool.getPool()**`](/cetus-developer-docs/developer/via-sdk/features-available/get-clmm-pools#id-3.-retrieve-one-pool) . #### [](#example) Example Copy import BN from 'bn.js' import { adjustForSlippage, d, initCetusSDK, Percentage, TransactionUtil } from '@cetusprotocol/cetus-sui-clmm-sdk' const sdk = initCetusSDK({ network: 'mainnet' }) const a2b = false const pool = await sdk.Pool.getPool('0x6fd4915e6d8d3e2ba6d81787046eb948ae36fdfc75dad2e24f0d4aaa2417a416') const byAmountIn = false const amount = new BN(80000000000000) const swapTicks = await sdk.Pool.fetchTicks({ pool_id: pool.poolAddress, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB }) // const swapTicks = await sdk.Pool.fetchTicksByRpc(pool.ticks_handle) console.log("swapTicks length: ", swapTicks.length); const res = sdk.Swap.calculateRates({ decimalsA: 6, decimalsB: 6, a2b, byAmountIn, amount, swapTicks, currentPool: pool }) console.log('calculateRates###res###', { estimatedAmountIn: res.estimatedAmountIn.toString(), estimatedAmountOut: res.estimatedAmountOut.toString(), estimatedEndSqrtPrice: res.estimatedEndSqrtPrice.toString(), estimatedFeeAmount: res.estimatedFeeAmount.toString(), isExceed: res.isExceed, extraComputeLimit: res.extraComputeLimit, amount: res.amount.toString(), aToB: res.aToB, byAmountIn: res.byAmountIn, }) console.log('swap: ', transferTxn) [](#preswap-by-simulation-transaction) Preswap by simulation transaction ----------------------------------------------------------------------------- [](#preswap) preSwap ------------------------- use `sdk.Swap.preswap` method. #### [](#function-input-param-1) Function input param _Please refer to the original function for specific parameter types._ * `**pool**`: pool object, you can get it by `sdk.Pool.getPool()` method. * `**currentSqrtPrice**`: pool's current\_sqrt\_price. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**decimalsA**`: the decimal of coinA. * `**decimalsB**`: the decimal of coinB. * `**a2b**`: swap direction, `true` means swap from coinA to coinB, `false` means swap from coinB to CoinA. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**amount**`: the amount of input (`byAmountIn` = `true`) or output (`byAmountIn` = `false`). #### [](#example-1) Example Copy const sendKeypair = buildTestAccount() // Whether the swap direction is token a to token b const a2b = true // fix input token amount const coinAmount = new BN(120000) // input token amount is token a const byAmountIn = true // slippage value const slippage = Percentage.fromDecimal(d(5)) // Fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // Estimated amountIn amountOut fee const res: any = await sdk.Swap.preswap({ pool: pool, current_sqrt_price: pool.current_sqrt_price, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, decimalsA: 6, // coin a 's decimals decimalsB: 8, // coin b 's decimals a2b, by_amount_in, amount, }) const partner = "0x8e0b7668a79592f70fbfb1ae0aebaf9e2019a7049783b9a4b6fe7c6ae038b528" const toAmount = byAmountIn ? res.estimatedAmountOut : res.estimatedAmountIn const amountLimit = adjustForSlippage(toAmount, slippage, !byAmountIn) // build swap Payload const swapPayload = sdk.Swap.createSwapTransactionPayload( { pool_id: pool.poolAddress, coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB a2b: a2b, by_amount_in: by_amount_in, amount: res.amount.toString(), amount_limit: amountLimit.toString(), swap_partner: partner }, ) onst transferTxn = await sendTransaction(signer,swapPayload) console.log('swap: ', transferTxn) [](#preswapwithmultipool) preSwapWithMultiPool --------------------------------------------------- use `sdk.Swap.preSwapWithMultiPool()` method. #### [](#function-input-param-2) Function input param _Please refer to the original function for specific parameter types._ * `**poolAddresses**`:An array of pool objects ID. All pools must have the same type. * `**coinTypeA**`: the coin type address about coinA. * `**coinTypeB**`: the coin type address about coinB. * `**a2b**`: swap direction, `true` means swap from coinA to coinB, `false` means swap from coinB to CoinA. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**amount**`: the amount of input (`byAmountIn` = `true`) or output (`byAmountIn` = `false`). #### [](#example-2) Example Copy const a2b = true const poolAddresses = [\ '0x53d70570db4f4d8ebc20aa1b67dc6f5d061d318d371e5de50ff64525d7dd5bca',\ '0x4038aea2341070550e9c1f723315624c539788d0ca9212dca7eb4b36147c0fcb',\ '0x6fd4915e6d8d3e2ba6d81787046eb948ae36fdfc75dad2e24f0d4aaa2417a416',\ ] const pool0 = await buildTestPool(sdk, poolAddresses[0]) const pool1 = await buildTestPool(sdk, poolAddresses[1]) const pool2 = await buildTestPool(sdk, poolAddresses[2]) const byAmountIn = true const amount = '10000000' const resWithMultiPool: any = await sdk.Swap.preSwapWithMultiPool({ poolAddresses: poolAddresses, coinTypeA: pool0.coinTypeA, coinTypeB: pool0.coinTypeB, a2b, byAmountIn, amount, }) [PreviousCollect rewards](/cetus-developer-docs/developer/via-sdk/features-available/collect-rewards) [NextSwap](/cetus-developer-docs/developer/via-sdk/features-available/swap) Last updated 1 month ago 💻 --- # Close position | Cetus Developer Docs [](#close-position) Close position --------------------------------------- When you withdraw all the liquidity from your position, you can decide whether to close the position. Please note that when closing the position, you must also withdraw all the current position's liquidity, fees, and rewards. #### [](#function-input-params) Function input params _Please refer to the original function for specific parameter types._ * `**poolID**`: The object id about which pool you want to operation. * `**posID**`: The object id about position. * `**minAmountA**`: The minimum amount of coin A that a user can acquire. * `**maxAmountB**`: The minimum amount of coin B that a user can acquire. Because of pool price will change, the amount of coin A and coin B will change. So the `min_amount_a` and `min_amount_a` means no matter how the price moves, the amount quantity that I need to receive at least is typically obtained by adding the amount potentially acquired through calculations to the slippage adjustment. * `**rewarderCoinTypes**`: If these not empty, it will collect rewarders in this position, if you already open the position. You can even determine which types of rewards you want to harvest by specifying the coin types you pass. #### [](#example) Example Copy const sendKeypair = buildTestAccount() // Fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // Fetch position data const position = await sdk.Position.getPositionInfo(position_object_id) // build tick data const lowerSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_lower_index) const upperSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_upper_index) const ticksHandle = pool.ticks_handle const tickLower = await sdk.Pool.getTickDataByIndex(ticksHandle, position.tick_lower_index) const tickUpper = await sdk.Pool.getTickDataByIndex(ticksHandle, position.tick_upper_index) // input liquidity amount for remove const liquidity = new BN(position.liquidity) // slippage value const slippageTolerance = new Percentage(new BN(5), new BN(100)) const curSqrtPrice = new BN(pool.current_sqrt_price) // Get token amount from liquidity. const coinAmounts = ClmmPoolUtil.getCoinAmountFromLiquidity(liquidity, curSqrtPrice, lowerSqrtPrice, upperSqrtPrice, false) // adjust token a and token b amount for slippage const { tokenMaxA, tokenMaxB } = adjustForCoinSlippage(coinAmounts, slippageTolerance, false) // get all rewarders of position const rewards: any[] = await sdk.Rewarder.posRewardersAmount(poolObjectId,pool.positions_handle, position_object_id) const rewardCoinTypes = rewards.filter((item) => Number(item.amount_owed) > 0).map((item)=> item.coin_address) // build close position payload const closePositionTransactionPayload = sdk.Position.closePositionTransactionPayload({ coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, min_amount_a: tokenMaxA.toString(), min_amount_b: tokenMaxB.toString(), rewarder_coin_types: [...rewardCoinTypes], pool_id: pool.poolAddress, pos_id: position_object_id, }) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair,closePositionTransactionPayload) console.log('close position: ', transferTxn) [PreviousRemove liquidity](/cetus-developer-docs/developer/via-sdk/features-available/remove-liquidity) [NextCollect fees](/cetus-developer-docs/developer/via-sdk/features-available/collect-fees) Last updated 8 months ago --- # Smart router v1 | Cetus Developer Docs [](#swap-in-the-best-router) Swap in the best router --------------------------------------------------------- Now, we support to seek the best swap route among all cetus pools. When there is no direct trading pool between two trading assets, the smart routing will automatically find the optimal trading path linked for the pair. If there is a direct trading pool between the trading pairs, the smart routing will not only search through all direct trading pools but also explore the optimal trading path among other routes connected by intermediate tokens to compare. It's important to note that if you want to use this feature, you need to pre-configure a trading path graph for this method. You'll need to maintain a list of pools and the corresponding decimals for each coin in the pools. There are two methods to get all pools: 1. (Stable) If you get all pools by sdk, like ask.Pool.getPools(), you can't get coin decimals, so you need to set coin decimal by yourself. 2. (Speedy) Get pool list from our API. The coin decimals were provided. * Testnet: https://api-sui.cetus.zone/v2/sui/pools\_info * Mainnet: https://api-sui.cetus.zone/v2/sui/pools\_info [](#pre-calculating) Pre-calculating ----------------------------------------- use `sdk.Router.price()` method. #### [](#function-input-param) Function input param _Please refer to the original function for specific parameter types._ * `**from**`: coin type of from coin. * `**to**`: coin type of to coin. * `**amount**`: amount of from coin. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**amount**`: the amount of input (`byAmountIn` = `true`) or output (`byAmountIn` = `false`). * `**priceSplitPoint**`: split point of price, it control the range of coin losses you may incur. * `**partner**`: Partner object id. * `**swapWithMultiPoolParams**`: This is an option about the coin pair what you want to do swap, this is to prevent potential pre-calculation errors in the SDK. In such cases, if there are direct trading pools available, the routing will undergo a downgrade process. [](#build-router-v1-swap-transaction) Build router v1 swap transaction --------------------------------------------------------------------------- use `TransactionUtil.buildRouterSwapTransaction` method. #### [](#function-input-param-1) Function input param _Please refer to the original function for specific parameter types._ * `**sdk**`: The sdk include all import config. * `**params**`: pre-calculating result. 1. `**paths**`: paths of router swap result. 2. `**partner**`: Partner object id. 3. `**priceSlippagePoint**`: Slippage point of price, it control the range of coin losses you may incur. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**allCoinAsset**`: user's all coin object id. * `**recipient**`: (Option) the address about all coins recipient. If recipient not set, transfer objects move call will use sender get by ctx. Please update the SDK to the latest version 3.17.3+, and no longer use the SDK's default senderAddress as the recipient for transferObjects. #### [](#example) Example All used type in `/src/modules/routerModule.ts`. 1. **Get all pools by SDK.** Copy // get all pool info by `getPool`s. const pools = await sdk.Pool.getPools([], 0, 200) // prepare the data for constructing a transaction path graph. const coinMap = new Map() const poolMap = new Map() for (let i = 0; i < pools.length; i += 1) { if (pools[i].is_pause) { continue } let coin_a = pools[i].coinTypeA let coin_b = pools[i].coinTypeB // Get coin decimals individual coinMap.set(coin_a, { address: coin_a, decimals: coin_a_decimal, }) coinMap.set(coin_b, { address: coin_b, decimals: coin_b_decimal, }) const pair = `${coin_a}-${coin_b}` const pathProvider = poolMap.get(pair) if (pathProvider) { pathProvider.addressMap.set(pools[i].fee_rate, pools[i].poolAddress) } else { poolMap.set(pair, { base: coin_a, quote: coin_b, addressMap: new Map([[pools[i].fee_rate, pools[i].poolAddress]]), }) } } const coins: CoinProvider = { coins: Array.from(coinMap.values()) } const paths: PathProvider = { paths: Array.from(poolMap.values()) } // Load the path graph. sdk.Router.loadGraph(coins, paths) // The first two addresses requiring coin types. const byAmountIn = false const amount = new BN('1000000000000') const result = await sdk.Router.price(ETH, CETUS, amount, byAmountIn, 0.05, '') const params: SwapWithRouterParams = { paths: [result?.paths![0]!, result?.paths![1]!], partner: '', priceSplitPoint: 0.005, } // if find the best swap router, then send transaction. if (!result?.isExceed) { const allCoinAsset = await sdk.Resources.getOwnerCoinAssets(sdk.senderAddress) const payload = await TransactionUtil.buildRouterSwapTransaction(sdk, params, byAmountIn, allCoinAsset) const signer = new RawSigner(sendKeypair, sdk.fullClient) const transferTxn = await sendTransaction(signer, payload) } 1. **Get all pools from centralized API.** Copy const coinMap = new Map() const poolMap = new Map() const resp: any = await fetch('https://api-sui.cetus.zone/v2/sui/pools_info', { method: 'GET' }) const poolsInfo = await resp.json() if (poolsInfo.code === 200) { for (const pool of poolsInfo.data.lp_list) { if (pool.is_closed) { continue } let coin_a = pool.coin_a.address let coin_b = pool.coin_b.address coinMap.set(coin_a, { address: pool.coin_a.address, decimals: pool.coin_a.decimals, }) coinMap.set(coin_b, { address: pool.coin_b.address, decimals: pool.coin_b.decimals, }) const pair = `${coin_a}-${coin_b}` const pathProvider = poolMap.get(pair) if (pathProvider) { pathProvider.addressMap.set(Number(pool.fee) * 100, pool.address) } else { poolMap.set(pair, { base: coin_a, quote: coin_b, addressMap: new Map([[Number(pool.fee) * 100, pool.address]]), }) } } } const coins: CoinProvider = { coins: Array.from(coinMap.values()), } const paths: PathProvider = { paths: Array.from(poolMap.values()), } sdk.Router.loadGraph(coins, paths) // The first two addresses requiring coin types. const byAmountIn = false const amount = new BN('1000000000000') const result = await sdk.Router.price(ETH, CETUS, amount, byAmountIn, 0.05, '') const params: SwapWithRouterParams = { paths: result.paths, partner: '0x...', priceSlippagePoint: 0.01, } // if find the best swap router, then send transaction. if (!result?.isExceed) { const allCoinAsset = await sdk.Resources.getOwnerCoinAssets(sdk.senderAddress) // If recipient not set, transfer objects move call will use ctx sender. const payload = await TransactionUtil.buildRouterSwapTransaction(sdk, params, byAmountIn, allCoinAsset) const signer = new RawSigner(sendKeypair, sdk.fullClient) const transferTxn = await sendTransaction(signer, payload) } [PreviousPartner swap](/cetus-developer-docs/developer/via-sdk/features-available/partner-swap) [NextSmart router v2](/cetus-developer-docs/developer/via-sdk/features-available/smart-router-v2) Last updated 1 year ago 💻 --- # Smart router v2 | Cetus Developer Docs [](#swap-in-the-best-router-v2) Swap in the best router v2 --------------------------------------------------------------- In the smart router v2, we mainly started supporting the split computation of optimal routes. To ensure that our functionality is stable, we also have a well-designed fallback scheme in place. If our backend HPC service terminates unexpectedly, we will restart the first version of the sdk for precomputation. As with the original router, you need to build the router group ahead of time to ensure that fallback scenarios are always available There are two method to get all pools: 1. (Stable) If you get all pools by sdk, like ask.Pool.getPools(), you can't get coin decimals, so you need to set coin decimal by youself. 2. (Speedy) Get pool list from our API. The coin decimals are provided. Network Link **Testnet** **Mainnet** https://api-sui.cetus.zone/v2/sui/pools\_info In the latest version, we recommand you to build transaction by `TransactionUtil.buildAggregatorSwapTransaction`. All used type in `/src/modules/routerModule.ts`. If you want to use SDK to get pool list, you can see the method in router v1 doc. [](#pre-calculating) Pre-calculating ----------------------------------------- #### [](#function-input-param) Function input param _Please refer to the original function for specific parameter types._ * `**from**`: coin type of from coin. * `**to**`: coin type of to coin. * `**amount**`: amount of from coin. * `**byAmountIn**`: `true` means fixed the amount of input, `false` means fixed the amount of output. * `**amount**`: the amount of input (`byAmountIn` = `true`) or output (`byAmountIn` = `false`). * `**priceSplitPoint**`: split point of price, it control the range of coin losses you may incur. * `**partner**`: Partner object id. * `**swapWithMultiPoolParams**`: This is an option about the coin pair what you want to do swap, this is to prevent potential pre-calculation errors in the SDK. In such cases, if there are direct trading pools available, the routing will undergo a downgrade process. * `**orderSplit**`: Is the order splitting calculation feature enabled. * `**externalRouter**`: Is integrate external swap pool, now just support `deepbook`. Notice: Now, in smart router, if you open enable options: `orderSplit` or `externalRouter`, it can't support Partner. In this example, if you want to use partner function, `orderSplit` and `externalRouter` must set `false`. Copy async getBestRouter( from: string, to: string, amount: number, byAmountIn: boolean, priceSplitPoint: number, partner: string, senderAddress: string, swapWithMultiPoolParams?: PreSwapWithMultiPoolParams, orderSplit = false, externalRouter = false ) { result: AggregatorResult, version: 'v1' | 'v2'} [](#build-router-v2-swap-transaction) Build router v2 swap transaction --------------------------------------------------------------------------- use `TransactionUtil.buildAggregatorSwapTransaction` method. #### [](#function-input-param-1) Function input param _Please refer to the original function for specific parameter types._ * `**sdk**`: The sdk include all import config. * `**params**`: aggregator result in `**getBestRouter**`**.** * `**allCoinAsset**`: user's all coin object id. * `**partner**`**:** partner object id. If don't create partner, just set empty string(""). * `**priceSlippagePoint**`: Slippage point of price, it control the range of coin losses you may incur. * `**recipient**`: (Option) the address about all coins recipient. If recipient not set, transfer objects move call will use sender get by ctx. Please update the SDK to the latest version 3.17.3+ , and no longer use the SDK's default senderAddress as the recipient for transferObjects. #### [](#example) Example Get all pools by centralization API. If you want to get all pools by SDK, you can see router tutorial. Ps: In this example, i will swap 1k SUI to USDC. Copy import BN from 'bn.js' const coinMap = new Map() const poolMap = new Map() const resp: any = await fetch('https://api-sui.cetus.zone/v2/sui/pools_info', { method: 'GET' }) const poolsInfo = await resp.json() if (poolsInfo.code === 200) { for (const pool of poolsInfo.data.lp_list) { if (pool.is_closed) { continue } let coin_a = pool.coin_a.address let coin_b = pool.coin_b.address coinMap.set(coin_a, { address: pool.coin_a.address, decimals: pool.coin_a.decimals, }) coinMap.set(coin_b, { address: pool.coin_b.address, decimals: pool.coin_b.decimals, }) const pair = `${coin_a}-${coin_b}` const pathProvider = poolMap.get(pair) if (pathProvider) { pathProvider.addressMap.set(Number(pool.fee) * 100, pool.address) } else { poolMap.set(pair, { base: coin_a, quote: coin_b, addressMap: new Map([[Number(pool.fee) * 100, pool.address]]), }) } } } const coins: CoinProvider = { coins: Array.from(coinMap.values()), } const paths: PathProvider = { paths: Array.from(poolMap.values()), } sdk.Router.loadGraph(coins, paths) // The first two addresses requiring coin types. const fromCoin = "0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI" const toCoin = "0x5d4b302506645c37ff133b98c4b50a5ae14841659738d6d733d59d0d217a93bf::coin::COIN" const amount = new BN('1000000000000') const byAmountIn = false const priceSplitPoint = 0.5 const partner = '' const result = (await sdk.RouterV2.getBestRouter(fromCoin, toCoin, amount, byAmountIn, priceSplitPoint, partner, undefined, undefined, true, false)) .result as AggregatorResult // If find the best swap router, then send transaction. if (!result?.isExceed) { const allCoinAsset = await sdk.Resources.getOwnerCoinAssets(sdk.senderAddress) // If recipient not set, transfer objects move call will use ctx sender. const payload = await TransactionUtil.buildAggregatorSwapTransaction(sdk, res, allCoinAsset, '', 0.5) const signer = new RawSigner(sendKeypair, sdk.fullClient) const transferTxn = await sendTransaction(signer, payload) } [PreviousSmart router v1](/cetus-developer-docs/developer/via-sdk/features-available/smart-router-v1) [NextPrice impact](/cetus-developer-docs/developer/via-sdk/features-available/price-impact) Last updated 17 days ago 💻 [https://api-sui.cetus.zone/v2/sui/pools\_info](https://api-sui.devcetus.com/v2/sui/pools_info) --- # via Contract | Cetus Developer Docs [PreviousChangelog](/cetus-developer-docs/developer/via-sdk/changelog) [NextGetting Started](/cetus-developer-docs/developer/via-contract/getting-started) Last updated 23 days ago [](#introduction) Introduction ----------------------------------- This is an endpoint contract to help everyone integrate with the Cetus CLMM contract. [](#clmm) Clmm ------------------- Tag of Repo Network Clmmpool contract latest published at address mainnet-v1.26.0 mainnet 0xc6faf3703b0e8ba9ed06b7851134bbbe7565eb35ff823fd78432baa4cbeaa12e testnet-v1.26.0 testnet 0xb2a1d27337788bda89d350703b8326952413bd94b35b9b573ac8401b9803d018 [](#dca) DCA ----------------- Tag of Repo Network Latest published at address mainnet-v1.25.0 mainnet 0x587614620d0d30aed66d86ffd3ba385a661a86aa573a4d579017068f561c6d8f testnet-v1.25.0 testnet 0x19dd42e05fa6c9988a60d30686ee3feb776672b5547e328d6dab16563da65293 [](#limitorder) LimitOrder ------------------------------- Tag of Repo Network Latest published at address mainnet-v1.25.0 mainnet 0x533fab9a116080e2cb1c87f1832c1bf4231ab4c32318ced041e75cc28604bba9 testnet-v1.25.0 testnet 0xc65bc51d2bc2fdbce8c701f8d812da80fb37dba9cdf97ce38f60ab18c5202b17 [](#lp-burn) LP Burn ------------------------- Tag of Repo Network Latest published at address mainnet-v1.25.1 mainnet 0xb6ec861eec8c550269dc29a1662008a816ac4756df723af5103075b665e32e65 testnet-v1.25.1 testnet 0x9c751fccc633f3ebad2becbe7884e5f38b4e497127689be0d404b24f79d95d71 [](#stable-farming) Stable Farming --------------------------------------- Tag of Repo Network Latest published at address mainnet-v1.25.0 mainnet 0x7e4ca066f06a1132ab0499c8c0b87f847a0d90684afa902e52501a44dbd81992 testnet-v1.25.0 testnet **0x3c4582ee27a09f7e6c091022d0d279fdc8e54c1f782916bf135a71a8e8006aa5** [](#xcetus) Xcetus ----------------------- Tag of Repo Network Latest published at address mainnet-v1.24.0 mainnet 0x9e69acc50ca03bc943c4f7c5304c2a6002d507b51c11913b247159c60422c606 testnet-v1.24.0 testnet 0xdebaab6b851fd3414c0a62dbdf8eb752d6b0d31f5cfce5e38541bc6c6daa8966 [](#dividend) Dividend --------------------------- Tag of Repo Network Latest published at address mainnet-v1.25.0 mainnet 0x5aa58e1623885bd93de2331d05c29bf4930e54e56beeabcab8fe5385de2d31dc testnet-v1.25.0 testnet 0x20d948d640edd0c749f533d41efc5f843f212d441220324ad7959c6e1d281828 💻 [![Logo](https://github.com/fluidicon.png)GitHub - CetusProtocol/cetus-clmm-interfaceGitHub](https://github.com/CetusProtocol/cetus-clmm-interface) cetus-clmm-interface --- # APR correlation calculation | Cetus Developer Docs [](#id-1.-pool-apr) 1\. **Pool APR** ----------------------------------------- We have integrated the calculation of the pool's APR into our statistics service, and now you can directly obtain these data through the statistics interface. **Pool Info API** * Mainnet: https://api-sui.cetus.zone/v2/sui/swap/count * Testnet: https://api-sui.devcetus.com/v2/sui/swap/count There are three type apr you can get. * 24 h: data.pools\[x\].apr\_24h * 7 day: data.pools\[x\].apr\_7day * 30 day: data.pools\[x\].apr\_30day [](#id-2.-position-apr) 2\. **Position APR** ------------------------------------------------- 1.We use the `estPositionAPRWithMultiMethod` method in the SDK to calculate the multi coefficient `m`, and the parameters passed to this method come from the Cetus statistics interface. 2. Use coefficient `m` multiply the reward APRs respectively and then add them together. Copy export function estPositionAPRWithMultiMethod( lowerUserPrice: number, upperUserPrice: number, lowerHistPrice: number, upperHistPrice: number ) {} **Param explanation** * lowerUserPrice and upperUserPrice are the price of one position. * lowerHistPrice and upperHistPrice are come from the cetus statistics interface. **Price Statistics API** * Mainnet: [](https://api-sui.cetus.zone/v2/sui/contract/price) https://api-sui.cetus.zone/v2/sui/contract/price * Testnet: https://api-sui.devcetus.com/v2/sui/contract/price lowerHistPrice and upperHistPrice come from data.list\[x\].data\[x\]. there are three types `before_24_h_xx 、` `before_7_d_xx` and `before_30_d_xx.` Copy { "is_forward": true, "swap_account": "0x06f18e7826ee6c6d5bdc29ab3bed659d5dcd319cc184a008ce06b118f015cee4", "data": [\ {\ "key": "now_contract_price",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "now_contract_price_highest",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "now_contract_price_lowest",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_24_h_contract_price",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_24_h_contract_price_highest",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_24_h_contract_price_lowest",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_7_d_contract_price",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_7_d_contract_price_highest",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_7_d_contract_price_lowest",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_30_d_contract_price",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ },\ {\ "key": "before_30_d_contract_price_highest",\ "value": "0.9999999999999999999972756370986134019159358813153087168627718612"\ },\ {\ "key": "before_30_d_contract_price_lowest",\ "value": "0.9992102901095463005800349572310369144473236243054765866662672742"\ }\ ], "ticks": { "now": { "lower": 68800, "upper": 69200, "raw_lower": 69073, "raw_upper": 69073 }, "day": { "lower": 68800, "upper": 69200, "raw_lower": 69073, "raw_upper": 69073 }, "week": { "lower": 68800, "upper": 69200, "raw_lower": 69073, "raw_upper": 69073 }, "month": { "lower": 68800, "upper": 69200, "raw_lower": 69073, "raw_upper": 69081 } } }, The pool rewards apr come from the above mentioned pool info API, `data.pools[x].rewarder_apr`. [PreviousLiquidity and coin amounts calculation](/cetus-developer-docs/developer/via-sdk/features-available/liquidity-and-coin-amounts-calculation) [NextPrice, tick index and sqrt price correlation calculation](/cetus-developer-docs/developer/via-sdk/features-available/price-tick-index-and-sqrt-price-correlation-calculation) Last updated 2 months ago 💻 --- # Remove liquidity | Cetus Developer Docs When you want to adjust the liquidity of your position or withdraw liquidity from the position, you can use the following method. When you withdraw liquidity, you also have the option to collect fees or rewards at the same time. Please refer to the parameter description below for more details. [](#remove-liquidity-by-inputting-liquidity-value) Remove liquidity by inputting liquidity value ----------------------------------------------------------------------------------------------------- use `sdk.Position.removeLiquidityTransactionPayload()` method. #### [](#function-input-params) Function input params _Please refer to the original function for specific parameter types._ * `**poolID**`: The object id about which pool you want to operation. * `**posID**`: The object id about position. * `**deltaLiquidity**`: The quantity of liquidity. * `**minAmountA**`: The minimum amount of coin A that a user can acquire. * `**maxAmountB**`: The minimum amount of coin B that a user can acquire. Because of pool price will change, the amount of coin A and coin B will change. So the `min_amount_a` and `min_amount_a` means no matter how the price moves, the amount quantity that I need to receive at least is typically obtained by adding the amount potentially acquired through calculations to the slippage adjustment. * `**collectFee**`: you can select collect fees while adding liquidity. * `**rewarderCoinTypes**`: If these not empty, it will collect rewarders in this position, if you already open the position. You can even determine which types of rewards you want to harvest by specifying the coin types you pass. #### [](#example) Example Copy const sendKeypair = buildTestAccount() // Fetch pool data const pool = await sdk.Pool.getPool(poolAddress) // Fetch position data const position = await sdk.Position.getPositionInfo(position_object_id) // build tick data const lowerSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_lower_index) const upperSqrtPrice = TickMath.tickIndexToSqrtPriceX64(position.tick_upper_index) const ticksHandle = pool.ticks_handle const tickLower = await sdk.Pool.getTickDataByIndex(ticksHandle, position.tick_lower_index) const tickUpper = await sdk.Pool.getTickDataByIndex(ticksHandle, position.tick_upper_index) // input liquidity amount for remove const liquidity = new BN(10000) // slippage value const slippageTolerance = new Percentage(new BN(5), new BN(100)) const curSqrtPrice = new BN(pool.current_sqrt_price) // Get token amount from liquidity. const coinAmounts = ClmmPoolUtil.getCoinAmountFromLiquidity(liquidity, curSqrtPrice, lowerSqrtPrice, upperSqrtPrice, false) // adjust token a and token b amount for slippage const { tokenMaxA, tokenMaxB } = adjustForCoinSlippage(coinAmounts, slippageTolerance, false) // build remove liquidity params const removeLiquidityParams : RemoveLiquidityParams = { coinTypeA: pool.coinTypeA, coinTypeB: pool.coinTypeB, delta_liquidity: liquidity.toString(), min_amount_a: tokenMaxA.toString(), min_amount_b: tokenMaxB.toString(), pool_id: pool.poolAddress, pos_id: position.pos_object_id collect_fee: true // Whether to collect fee } const removeLiquidityTransactionPayload = sdk.Position.removeLiquidityTransactionPayload(removeLiquidityParams) const transferTxn = await sdk.fullClient.sendTransaction(sendKeypair, removeLiquidityTransactionPayload) console.log('removeLiquidity: ', transferTxn) [PreviousAdd liquidity](/cetus-developer-docs/developer/via-sdk/features-available/add-liquidity) [NextClose position](/cetus-developer-docs/developer/via-sdk/features-available/close-position) Last updated 6 days ago --- # Minimum received & Maximum sold | Cetus Developer Docs [](#how-to-calculate-minimun-received) How to calculate minimun received? ------------------------------------------------------------------------------ When fixed input amount, **minimum received** means the min amount of the received coin, it equals `outputAmount * (1 - slippageTolerance)`.If swap during times of significant price fluctuations, and swap result of output amount less than minimum received, this transaction will be rejected. #### [](#example) Example Copy const res = await sdk.RouterV2.getBestRouter(USDT, USDC, 100000000, true, 5, '', undefined, true, false) const slippageTolerance = 0.01 const minReceived = res.result.outputAmount * (1 - slippageTolerance) console.log('minReceived: ', minReceived ) [](#undefined) ------------------ [](#how-to-calculate-maximum-sold) How to calculate maximum sold? ---------------------------------------------------------------------- When fixed output amount, **maximum sold** means the max amount of the sold coin, it equals `inputAmount * (1 + slippageTolerance)`.If swap during times of significant price fluctuations, and swap result of input amount more than maximum sold, this transaction will be rejected. #### [](#example-1) Example Copy const res = await sdk.RouterV2.getBestRouter(USDT, USDC, 100000000, true, 5, '', undefined, true, false) const slippageTolerance = 0.01 const maxSold = res.result.inputAmount * (1 + slippageTolerance) console.log('maxSold: ', maxSold ) [PreviousPrice impact](/cetus-developer-docs/developer/via-sdk/features-available/price-impact) [NextFee](/cetus-developer-docs/developer/via-sdk/features-available/fee) Last updated 1 year ago --- # Data Structure | Cetus Developer Docs [](#clmm) Clmm ------------------- ### [](#id-1.-position) 1\. Position Copy /// The Cetus clmmpool's position NFT. struct Position has key, store { id: UID, pool: ID, index: u64, coin_type_a: TypeName, coin_type_b: TypeName, name: String, description: String, url: String, tick_lower_index: I32, tick_upper_index: I32, liquidity: u128, } ### [](#id-2.-rewarder) 2\. Rewarder Copy struct Rewarder has copy, drop, store { reward_coin: TypeName, emissions_per_second: u128, growth_global: u128, } ### [](#id-3.-pool) 3\. Pool Copy /// The clmmpool struct Pool has key, store { id: UID, coin_a: Balance, coin_b: Balance, /// The tick spacing tick_spacing: u32, /// The numerator of fee rate, the denominator is 1_000_000. fee_rate: u64, /// The liquidity of current tick index liquidity: u128, /// The current sqrt price current_sqrt_price: u128, /// The current tick index current_tick_index: I32, /// The global fee growth of coin a,b as Q64.64 fee_growth_global_a: u128, fee_growth_global_b: u128, /// The amounts of coin a,b owend to protocol fee_protocol_coin_a: u64, fee_protocol_coin_b: u64, /// The tick manager tick_manager: TickManager, /// The rewarder manager rewarder_manager: RewarderManager, /// The position manager position_manager: PositionManager, /// is the pool pause is_pause: bool, /// The pool index index: u64, /// The url for pool and postion url: String, } ### [](#id-4.-addliquidityreceipt) 4\. AddLiquidityReceipt Copy /// Flash loan resource for add_liquidity struct AddLiquidityReceipt { pool_id: ID, amount_a: u64, amount_b: u64 } [](#id-5.-flashswapreceipt) 5\. FlashSwapReceipt ----------------------------------------------------- Copy /// Flash loan resource for swap. /// There is no way in Move to pass calldata and make dynamic calls, but a resource can be used for this purpose. /// To make the execution into a single transaction, the flash loan function must return a resource /// that cannot be copied, cannot be saved, cannot be dropped, or cloned. struct FlashSwapReceipt { pool_id: ID, a2b: bool, partner_id: ID, pay_amount: u64, ref_fee_amount: u64 } [PreviousGetting Started](/cetus-developer-docs/developer/via-contract/getting-started) [NextFeatures Available](/cetus-developer-docs/developer/via-contract/features-available) Last updated 3 months ago 💻 ---