### Query Market Depth with IRouter Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Use `get_market_depth_v2` to find the total liquidity available within a percentage of the current price. `get_market_depth_at_sqrt_ratio` allows querying from a specific price, and `get_delta_to_sqrt_ratio` calculates the token amounts needed to reach a target price. ```cairo use ekubo::interfaces::router::{IRouterDispatcher, IRouterDispatcherTrait, Depth}; let router = IRouterDispatcher { contract_address: ROUTER_ADDRESS }; // Market depth within ±2% (percent_64x64 = floor(0.02 * 2**64)) let percent_64x64: u128 = 369368101135919872_u128; // 2% in 64.64 format let depth: Depth = router.get_market_depth_v2(pool_key, percent_64x64); // depth.token0 = total token0 available to buy within 2% price move // depth.token1 = total token1 available to buy within 2% price move // Depth starting from an arbitrary price let depth_at: Depth = router.get_market_depth_at_sqrt_ratio( pool_key, 340282366920938463463374607431768211456_u256, // custom sqrt_ratio percent_64x64, ); // Get token amounts needed to move pool to a specific price use ekubo::types::delta::Delta; let cost: Delta = router.get_delta_to_sqrt_ratio( pool_key, MIN_SQRT_RATIO, // target price ); ``` -------------------------------- ### Manage LP Positions with IPositions::mint_v2, deposit_amounts, withdraw_v2 Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Use these functions to create, fund, and manage liquidity provider positions represented by NFTs. Ensure tokens are approved before depositing. The `get_token_info` function provides details on current amounts and fees. ```cairo use ekubo::interfaces::positions::{IPositionsDispatcher, IPositionsDispatcherTrait}; use ekubo::types::bounds::Bounds; use ekubo::types::i129::i129; use ekubo::types::keys::PoolKey; use starknet::contract_address_const; let positions = IPositionsDispatcher { contract_address: POSITIONS_ADDRESS }; // 1. Mint a new position NFT (no pool/bounds binding yet in v2) let token_id: u64 = positions.mint_v2( contract_address_const::<0x0>(), // referrer (zero = none) ); // 2. Approve the Positions contract to spend your tokens first, then deposit let bounds = Bounds { lower: i129 { mag: 1000_u128, sign: true }, upper: i129 { mag: 1000_u128, sign: false }, }; let liquidity_added: u128 = positions.deposit_amounts( token_id, pool_key, bounds, 500_u128, // amount0 to deposit 500_u128, // amount1 to deposit 0_u128, // min_liquidity (slippage guard) ); // 3. Query current principal and fees let info = positions.get_token_info(token_id, pool_key, bounds); // info.amount0, info.amount1 — current token amounts // info.fees0, info.fees1 — uncollected fees // info.liquidity — active liquidity units // info.pool_price — current pool price // 4. Collect fees without touching principal let (fee0, fee1) = positions.collect_fees(token_id, pool_key, bounds); // 5. Remove half the liquidity, enforce minimums let (out0, out1) = positions.withdraw_v2( token_id, pool_key, bounds, liquidity_added / 2, 100_u128, // min_token0 100_u128, // min_token1 ); // Atomic convenience: mint + deposit in one call let (new_id, liq) = positions.mint_and_deposit(pool_key, bounds, 0_u128 /* min_liq */); ``` -------------------------------- ### Construct and Use i129 Signed Integers Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Demonstrates the construction of positive and negative i129 values, arithmetic operations, predicate helpers, and conversion to/from u128. Use i129 for signed amounts in Ekubo. ```cairo use ekubo::types::i129::{i129, i129Trait, AddDeltaTrait}; use core::num::traits::Zero; // Construct positive and negative values let positive: i129 = i129 { mag: 1000_u128, sign: false }; // +1000 let negative: i129 = i129 { mag: 500_u128, sign: true }; // -500 // Arithmetic let sum = positive + negative; // i129 { mag: 500, sign: false } → +500 let diff = positive - negative; // i129 { mag: 1500, sign: false } → +1500 let prod = positive * negative; // i129 { mag: 500000, sign: true } → -500000 // Predicate helpers assert!(!positive.is_negative()); assert!(negative.is_negative()); assert!(Zero::is_zero(@i129 { mag: 0, sign: false })); // Apply a signed delta to a u128 balance let balance: u128 = 2000_u128; let new_bal = balance.add(positive); // 2000 + 1000 = 3000 let new_bal2 = balance.sub(positive); // 2000 - 1000 = 1000 // Convert from i128 let from_i128: i129 = (-42_i128).into(); // i129 { mag: 42, sign: true } // TryInto u128 — fails for negative values let ok: Option = positive.try_into(); // Some(1000) let fail: Option = negative.try_into(); // None ``` -------------------------------- ### Place and Close Limit Orders with IPositions Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Use `mint_and_place_limit_order` to place a limit order that converts when the market price crosses the specified tick. `close_limit_order` can be used to close the order at any time, returning any remaining tokens. ```cairo use ekubo::interfaces::positions::{IPositionsDispatcher, IPositionsDispatcherTrait}; use ekubo::interfaces::extensions::limit_orders::OrderKey as LimitOrderKey; use ekubo::types::i129::i129; use starknet::contract_address_const; let positions = IPositionsDispatcher { contract_address: POSITIONS_ADDRESS }; // Sell token1 at tick +2000 (sell token1 when price is above this tick) let order_key = LimitOrderKey { token0: ETH_ADDRESS, token1: USDC_ADDRESS, tick: i129 { mag: 2000_u128, sign: false }, // tick determines direction }; // Approve positions for the sell amount, then place let (token_id, liquidity): (u64, u128) = positions.mint_and_place_limit_order(order_key, 1000_u128 /* sell amount */); // Query if the order has been filled let order_infos = positions.get_limit_orders_info( array![(token_id, order_key)].span(), ); let result = *order_infos.at(0); // result.executed → true if order fully filled // result.amount0 → token0 received // result.amount1 → token1 received // Close the order (filled or not) and collect tokens let (recv0, recv1) = positions.close_limit_order(token_id, order_key); // Returns remaining sell amount + any purchased amount ``` -------------------------------- ### Initializing a Liquidity Pool with ICore::initialize_pool Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Use ICore::initialize_pool to create a new liquidity pool. This function can be called outside a lock as it does not transfer tokens. It returns the initial sqrt_ratio. The maybe_initialize_pool variant is idempotent and does nothing if the pool already exists. ```cairo use ekubo::interfaces::core::{ICoreDispatcher, ICoreDispatcherTrait}; use ekubo::types::keys::PoolKey; use ekubo::types::i129::i129; use starknet::contract_address_const; let core = ICoreDispatcher { contract_address: CORE_ADDRESS }; let pool_key = PoolKey { token0: contract_address_const::<0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7>(), token1: contract_address_const::<0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8>(), fee: 1701411834604692317316873037158841057280_u128, // 0.5% tick_spacing: 1000_u128, extension: contract_address_const::<0x0>(), }; // Start the pool at tick 0 (approximately 1:1 price) let initial_tick = i129 { mag: 0_u128, sign: false }; let sqrt_ratio: u256 = core.initialize_pool(pool_key, initial_tick); // sqrt_ratio ≈ 340282366920938463463374607431768211456 (2**128) // Idempotent variant — no-op if pool already exists let maybe: Option = core.maybe_initialize_pool(pool_key, initial_tick); ``` -------------------------------- ### Implement IExtension for Custom Pool Behavior Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Implement the IExtension interface to add custom logic to pool operations. Core automatically calls these hooks. Extensions can interact back with core within the same lock. ```cairo use ekubo::interfaces::core::{ IExtension, SwapParameters, UpdatePositionParameters, }; use ekubo::types::delta::Delta; use ekubo::types::i129::i129; use ekubo::types::keys::PoolKey; use starknet::ContractAddress; #[starknet::contract] mod FeeCollectorExtension { use super::*; #[abi(embed_v0)] impl ExtensionImpl of IExtension { fn before_initialize_pool( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, initial_tick: i129, ) { /* optional pre-init logic */ } fn after_initialize_pool( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, initial_tick: i129, ) { /* emit an event, configure pool metadata, etc. */ } fn before_swap( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: SwapParameters, ) { /* e.g. rate limiting, circuit breakers */ } fn after_swap( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: SwapParameters, delta: Delta, ) { // Accumulate 1 token0 as extra protocol fee after every swap let core = ICoreDispatcher { contract_address: CORE_ADDRESS }; core.accumulate_as_fees(pool_key, 1_u128, 0_u128); } fn before_update_position( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: UpdatePositionParameters, ) { } fn after_update_position( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: UpdatePositionParameters, delta: Delta, ) { } fn before_collect_fees( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, salt: felt252, bounds: Bounds, ) { } fn after_collect_fees( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, salt: felt252, bounds: Bounds, delta: Delta, ) { } } } ``` -------------------------------- ### Define Liquidity Position Bounds Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Illustrates creating Bounds for a liquidity position, specifying lower and upper tick limits. Bounds must be aligned with the pool's tick spacing and satisfy lower < upper. ```cairo use ekubo::types::bounds::{Bounds, max_bounds}; use ekubo::types::i129::i129; // Tight range around current price (ticks ~±1000) let bounds = Bounds { lower: i129 { mag: 1000_u128, sign: true }, // tick -1000 upper: i129 { mag: 1000_u128, sign: false }, // tick +1000 }; // Validate against a pool with tick_spacing = 200 bounds.check_valid(200_u128); // panics unless both ticks are multiples of 200 // Get the widest usable range for a given tick spacing let full_range: Bounds = max_bounds(1000_u128); // full_range.lower ≈ tick -88_722_000, full_range.upper ≈ tick +88_722_000 ``` -------------------------------- ### Define a PoolKey for Ekubo Pools Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Shows how to construct a PoolKey, which uniquely identifies an Ekubo pool using token addresses, fee rate, and tick spacing. Ensure token0 is the address with the lower value. ```cairo use ekubo::types::keys::PoolKey; use starknet::contract_address_const; // 0.3% fee pool with tick spacing 1000, no extension let pool_key = PoolKey { token0: contract_address_const::<0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7>(), // ETH (smaller addr) token1: contract_address_const::<0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8>(), // USDC fee: 1701411834604692317316873037158841057280_u128, // 0.5% = 2**128 / 200 tick_spacing: 1000_u128, extension: contract_address_const::<0x0>(), // no extension }; // Validate (panics if token0 >= token1, tick_spacing out of range) pool_key.check_valid(); ``` -------------------------------- ### IExtension Interface Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Interface for extensions to implement custom pool behavior by hooking into various pool lifecycle events. ```APIDOC ## IExtension — custom pool hook interface ### Implement `IExtension` to add custom pool behavior Any contract can be set as a pool's `extension`. Core calls the registered hooks automatically. The extension can call back into core (within the same lock) to perform additional swaps, update positions, or accumulate tokens as fees. ```cairo use ekubo::interfaces::core::{ IExtension, SwapParameters, UpdatePositionParameters, }; use ekubo::types::delta::Delta; use ekubo::types::i129::i129; use ekubo::types::keys::PoolKey; use starknet::ContractAddress; #[starknet::contract] mod FeeCollectorExtension { use super::*; #[abi(embed_v0)] impl ExtensionImpl of IExtension { fn before_initialize_pool( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, initial_tick: i129, ) { /* optional pre-init logic */ } fn after_initialize_pool( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, initial_tick: i129, ) { /* emit an event, configure pool metadata, etc. */ } fn before_swap( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: SwapParameters, ) { /* e.g. rate limiting, circuit breakers */ } fn after_swap( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: SwapParameters, delta: Delta, ) { // Accumulate 1 token0 as extra protocol fee after every swap let core = ICoreDispatcher { contract_address: CORE_ADDRESS }; core.accumulate_as_fees(pool_key, 1_u128, 0_u128); } fn before_update_position( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: UpdatePositionParameters, ) { } fn after_update_position( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, params: UpdatePositionParameters, delta: Delta, ) { } fn before_collect_fees( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, salt: felt252, bounds: Bounds, ) { } fn after_collect_fees( ref self: ContractState, caller: ContractAddress, pool_key: PoolKey, salt: felt252, bounds: Bounds, delta: Delta, ) { } } } ``` ``` -------------------------------- ### Perform Multi-Hop Swaps with IRouter Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Chain multiple swaps using `multihop_swap` to route a trade across different pools when a direct pool does not exist. Use `quote_multihop_swap` to simulate a swap without execution. ```cairo use ekubo::interfaces::router::{ IRouterDispatcher, IRouterDispatcherTrait, RouteNode, TokenAmount, Swap, }; use ekubo::types::i129::i129; use ekubo::types::keys::PoolKey; use ekubo::math::ticks::constants::{MIN_SQRT_RATIO, MAX_SQRT_RATIO}; let router = IRouterDispatcher { contract_address: ROUTER_ADDRESS }; // Route: ETH → STRK → USDC (two hops) let route = array![ RouteNode { pool_key: ETH_STRK_POOL_KEY, sqrt_ratio_limit: MIN_SQRT_RATIO, // allow full price movement skip_ahead: 0_u128, }, RouteNode { pool_key: STRK_USDC_POOL_KEY, sqrt_ratio_limit: MIN_SQRT_RATIO, skip_ahead: 0_u128, }, ]; // Sell 1 ETH (exact input), approve router first let deltas = router.multihop_swap( route, TokenAmount { token: ETH_ADDRESS, amount: i129 { mag: 1000000000000000000_u128, sign: false }, // +1 ETH }, ); // deltas[0].amount0 = +1 ETH consumed from caller // deltas[1].amount1 = -N USDC sent to caller // Simulate without executing (view function) let quote_deltas = router.quote_multihop_swap( array![ /* same route */ ], TokenAmount { token: ETH_ADDRESS, amount: i129 { mag: 1000000000000000000_u128, sign: false } }, ); ``` -------------------------------- ### IRouter::multihop_swap Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Enables routing swaps across multiple liquidity pools to facilitate trades between assets that do not have a direct pool. Supports both exact input and exact output swaps. ```APIDOC ## IRouter::multihop_swap — route a swap across multiple pools ### Description Chains multiple swaps so the output of each pool becomes the input of the next. Useful for pairs with no direct pool. For exact-output swaps, pass the route in reverse. ### Method `multihop_swap(route: array, token_amount: TokenAmount) -> array` `quote_multihop_swap(route: array, token_amount: TokenAmount) -> array` ### Parameters #### `multihop_swap` and `quote_multihop_swap` - **route** (array) - An array of `RouteNode` specifying the pools and price limits for the swap. - **token_amount** (TokenAmount) - The input token and amount for the swap. ### Request Example ```cairo use ekubo::interfaces::router::{IRouterDispatcher, IRouterDispatcherTrait, RouteNode, TokenAmount, Swap}; use ekubo::types::i129::i129; use ekubo::types::keys::PoolKey; use ekubo::math::ticks::constants::{MIN_SQRT_RATIO, MAX_SQRT_RATIO}; let router = IRouterDispatcher { contract_address: ROUTER_ADDRESS }; let route = array![ RouteNode { pool_key: ETH_STRK_POOL_KEY, sqrt_ratio_limit: MIN_SQRT_RATIO, skip_ahead: 0_u128, }, RouteNode { pool_key: STRK_USDC_POOL_KEY, sqrt_ratio_limit: MIN_SQRT_RATIO, skip_ahead: 0_u128, }, ]; // Sell 1 ETH (exact input) let deltas = router.multihop_swap( route, TokenAmount { token: ETH_ADDRESS, amount: i129 { mag: 1000000000000000000_u128, sign: false } }, ); // Simulate without executing (view function) let quote_deltas = router.quote_multihop_swap( array![ /* same route */ ], TokenAmount { token: ETH_ADDRESS, amount: i129 { mag: 1000000000000000000_u128, sign: false } }, ); ``` ### Response #### Success Response (for both `multihop_swap` and `quote_multihop_swap`) - **deltas** (array) - An array of `Delta` objects representing the net change in tokens for each hop. `deltas[0].amount0` is the input token consumed, and `deltas[last].amount1` is the output token received. ``` -------------------------------- ### IPositions::mint_and_place_limit_order / close_limit_order Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Allows users to place limit orders at tick-aligned prices and subsequently close them to collect tokens. It also provides functionality to query the status of placed orders. ```APIDOC ## IPositions::mint_and_place_limit_order / close_limit_order — place tick-aligned limit orders ### Description Places a limit order at the next tick-aligned price. The order converts fully when the market price crosses the order tick. It also allows closing the order and collecting tokens. ### Method `mint_and_place_limit_order(order_key: LimitOrderKey, sell_amount: u128) -> (token_id: u64, liquidity: u128)` `close_limit_order(token_id: u64, order_key: LimitOrderKey) -> (recv0: felt252, recv1: felt252)` ### Parameters #### `mint_and_place_limit_order` - **order_key** (LimitOrderKey) - Represents the order's parameters including tokens and tick. - **sell_amount** (u128) - The amount of tokens to sell. #### `close_limit_order` - **token_id** (u64) - The unique identifier for the limit order. - **order_key** (LimitOrderKey) - Represents the order's parameters including tokens and tick. ### Request Example ```cairo use ekubo::interfaces::positions::{IPositionsDispatcher, IPositionsDispatcherTrait}; use ekubo::interfaces::extensions::limit_orders::OrderKey as LimitOrderKey; use ekubo::types::i129::i129; use starknet::contract_address_const; let positions = IPositionsDispatcher { contract_address: POSITIONS_ADDRESS }; let order_key = LimitOrderKey { token0: ETH_ADDRESS, token1: USDC_ADDRESS, tick: i129 { mag: 2000_u128, sign: false }, }; let (token_id, liquidity) = positions.mint_and_place_limit_order(order_key, 1000_u128); let (recv0, recv1) = positions.close_limit_order(token_id, order_key); ``` ### Response #### `mint_and_place_limit_order` Success Response - **token_id** (u64) - The unique identifier for the newly placed order. - **liquidity** (u128) - The liquidity associated with the order. #### `close_limit_order` Success Response - **recv0** (felt252) - Amount of token0 received. - **recv1** (felt252) - Amount of token1 received. ### Related Functions - `get_limit_orders_info(order_keys: array<(_, _)>) -> array`: Queries the status of placed limit orders. ``` -------------------------------- ### Create TWAMM Order with IPositions::mint_and_increase_sell_amount Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Use this function to open a TWAMM order for gradual token selling over a specified period, minimizing price impact. The `get_order_info` function retrieves order status, and `withdraw_proceeds_from_sale_to_self` collects earnings. ```cairo use ekubo::interfaces::positions::{IPositionsDispatcher, IPositionsDispatcherTrait}; use ekubo::interfaces::extensions::twamm::OrderKey; use starknet::contract_address_const; let positions = IPositionsDispatcher { contract_address: POSITIONS_ADDRESS }; let order_key = OrderKey { sell_token: ETH_ADDRESS, buy_token: USDC_ADDRESS, fee: 1701411834604692317316873037158841057280_u128, // 0.5% start_time: 1700000000_u64, // Unix timestamp end_time: 1700086400_u64, // +24 hours }; // Approve Positions to spend 10_000 ETH, then open order let (token_id, sale_rate): (u64, u128) = positions.mint_and_increase_sell_amount(order_key, 10000_u128 /* amount */); // sale_rate = tokens per second being sold // Check order status let info = positions.get_order_info(token_id, order_key); // info.sale_rate — current sell rate (tokens/sec) // info.remaining_sell_amount — tokens yet to be sold // info.purchased_amount — tokens already received // Collect proceeds earned so far let received: u128 = positions.withdraw_proceeds_from_sale_to_self(token_id, order_key); // Reduce the sale rate (partial cancel), returns refunded amount let refunded: u128 = positions.decrease_sale_rate_to_self( token_id, order_key, sale_rate / 2, ); ``` -------------------------------- ### ICore::initialize_pool Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Creates a new liquidity pool identified by `pool_key` at `initial_tick`. This operation is idempotent and returns the initial `sqrt_ratio`. ```APIDOC ## ICore::initialize_pool ### Description Creates a new liquidity pool identified by `pool_key` at `initial_tick`. Can be called outside a lock because no tokens are transferred. Returns the initial `sqrt_ratio`. ### Method `initialize_pool(pool_key: PoolKey, initial_tick: i129) -> u256` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cairo use ekubo::interfaces::core::{ICoreDispatcher, ICoreDispatcherTrait}; use ekubo::types::keys::PoolKey; use ekubo::types::i129::i129; use starknet::contract_address_const; let core = ICoreDispatcher { contract_address: CORE_ADDRESS }; let pool_key = PoolKey { token0: contract_address_const::<0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7>(), token1: contract_address_const::<0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8>(), fee: 1701411834604692317316873037158841057280_u128, // 0.5% tick_spacing: 1000_u128, extension: contract_address_const::<0x0>(), }; // Start the pool at tick 0 (approximately 1:1 price) let initial_tick = i129 { mag: 0_u128, sign: false }; let sqrt_ratio: u256 = core.initialize_pool(pool_key, initial_tick); // sqrt_ratio ≈ 340282366920938463463374607431768211456 (2**128) ``` ### Response #### Success Response (200) - **sqrt_ratio** (u256) - The square root of the initial price ratio of the pool. #### Response Example ```json { "sqrt_ratio": "340282366920938463463374607431768211456" } ``` ## ICore::maybe_initialize_pool ### Description An idempotent variant of `initialize_pool`. If the pool already exists, this function does nothing and returns `None`. Otherwise, it creates the pool and returns `Some(sqrt_ratio)`. ### Method `maybe_initialize_pool(pool_key: PoolKey, initial_tick: i129) -> Option` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```cairo use ekubo::interfaces::core::{ICoreDispatcher, ICoreDispatcherTrait}; use ekubo::types::keys::PoolKey; use ekubo::types::i129::i129; use starknet::contract_address_const; let core = ICoreDispatcher { contract_address: CORE_ADDRESS }; let pool_key = PoolKey { token0: contract_address_const::<0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7>(), token1: contract_address_const::<0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8>(), fee: 1701411834604692317316873037158841057280_u128, // 0.5% tick_spacing: 1000_u128, extension: contract_address_const::<0x0>(), }; // Start the pool at tick 0 (approximately 1:1 price) let initial_tick = i129 { mag: 0_u128, sign: false }; let maybe: Option = core.maybe_initialize_pool(pool_key, initial_tick); ``` ### Response #### Success Response (200) - **maybe** (Option) - `Some(sqrt_ratio)` if the pool was created, `None` if it already existed. #### Response Example ```json { "maybe": "0x340282366920938463463374607431768211456" } ``` ``` -------------------------------- ### Manage LP Positions Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Functions for creating, depositing into, and withdrawing from LP positions using NFTs. ```APIDOC ## `IPositions::mint_v2` ### Description Mints a new position NFT. In v2, this does not immediately bind to a pool or bounds. ### Method `mint_v2` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **referrer** (contract_address) - Optional - The address of the referrer. ### Request Example ```cairo let token_id: u64 = positions.mint_v2( contract_address_const::<0x0>(), // referrer (zero = none) ); ``` ### Response #### Success Response (200) - **token_id** (u64) - The ID of the newly minted token. #### Response Example ```json { "token_id": 123 } ``` ``` ```APIDOC ## `IPositions::deposit_amounts` ### Description Adds liquidity to an existing position NFT. Requires prior approval of the Positions contract to spend tokens. ### Method `deposit_amounts` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **token_id** (u64) - Required - The ID of the position NFT. - **pool_key** (PoolKey) - Required - The key identifying the pool. - **bounds** (Bounds) - Required - The price bounds for the liquidity. - **amount0** (u128) - Required - The amount of token0 to deposit. - **amount1** (u128) - Required - The amount of token1 to deposit. - **min_liquidity** (u128) - Required - The minimum amount of liquidity to be added (slippage guard). ### Request Example ```cairo let liquidity_added: u128 = positions.deposit_amounts( token_id, pool_key, bounds, 500_u128, // amount0 to deposit 500_u128, // amount1 to deposit 0_u128, // min_liquidity (slippage guard) ); ``` ### Response #### Success Response (200) - **liquidity_added** (u128) - The amount of liquidity that was added. #### Response Example ```json { "liquidity_added": 1000 } ``` ``` ```APIDOC ## `IPositions::withdraw_v2` ### Description Removes liquidity from a position NFT. ### Method `withdraw_v2` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **token_id** (u64) - Required - The ID of the position NFT. - **pool_key** (PoolKey) - Required - The key identifying the pool. - **bounds** (Bounds) - Required - The price bounds of the liquidity. - **liquidity_to_remove** (u128) - Required - The amount of liquidity to remove. - **min_token0** (u128) - Required - The minimum amount of token0 to receive (slippage guard). - **min_token1** (u128) - Required - The minimum amount of token1 to receive (slippage guard). ### Request Example ```cairo let (out0, out1) = positions.withdraw_v2( token_id, pool_key, bounds, liquidity_added / 2, 100_u128, // min_token0 100_u128, // min_token1 ); ``` ### Response #### Success Response (200) - **out0** (u128) - The amount of token0 withdrawn. - **out1** (u128) - The amount of token1 withdrawn. #### Response Example ```json { "out0": 50, "out1": 50 } ``` ``` ```APIDOC ## `IPositions::mint_and_deposit` ### Description Atomically mints a new position NFT and deposits liquidity into it. ### Method `mint_and_deposit` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **pool_key** (PoolKey) - Required - The key identifying the pool. - **bounds** (Bounds) - Required - The price bounds for the liquidity. - **min_liquidity** (u128) - Required - The minimum amount of liquidity to be added (slippage guard). ### Request Example ```cairo let (new_id, liq) = positions.mint_and_deposit(pool_key, bounds, 0_u128 /* min_liq */); ``` ### Response #### Success Response (200) - **new_id** (u64) - The ID of the newly minted token. - **liq** (u128) - The amount of liquidity added. #### Response Example ```json { "new_id": 124, "liq": 1000 } ``` ``` -------------------------------- ### ILimitOrders::get_order_info / get_order_infos Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Inspects the state of limit orders, querying whether they have been executed and the resulting token amounts. ```APIDOC ## ILimitOrders::get_order_info ### Description Queries whether a limit order has been executed and the resulting token amounts received. ### Method `get_order_info` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **request** (GetOrderInfoRequest) - Required - The request object containing order details. - **owner** (address) - Required - The owner of the order. - **salt** (felt252) - Required - The salt used for the order. - **order_key** (OrderKey) - Required - The key identifying the order. - **token0** (address) - Required - **token1** (address) - Required - **tick** (i129) - Required - **mag** (u128) - Required - **sign** (bool) - Required ### Request Example ```cairo use ekubo::interfaces::extensions::limit_orders::{ ILimitOrdersDispatcher, GetOrderInfoRequest, OrderKey }; use ekubo::types::i129::i129; let limit_orders = ILimitOrdersDispatcher { contract_address: LIMIT_ORDERS_ADDRESS }; let request = GetOrderInfoRequest { owner: OWNER_ADDRESS, salt: 0_felt252, order_key: OrderKey { token0: ETH_ADDRESS, token1: USDC_ADDRESS, tick: i129 { mag: 2000_u128, sign: false }, }, }; let result: GetOrderInfoResult = limit_orders.get_order_info(request); ``` ### Response #### Success Response (200) - **executed** (bool) - True if the order has been fully filled. - **amount0** (u128) - Token0 amount to collect if closed now. - **amount1** (u128) - Token1 amount to collect if closed now. - **state** (OrderState) - The current state of the order. - **liquidity** (u128) - Deposited liquidity. #### Response Example ```json { "executed": true, "amount0": "...", "amount1": "...", "state": { "liquidity": "..." } } ``` ``` ```APIDOC ## ILimitOrders::get_order_infos ### Description Batch queries for the state of multiple limit orders. ### Method `get_order_infos` ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **requests** (array) - Required - An array of request objects for the orders to query. - Each element is a GetOrderInfoRequest object: - **owner** (address) - Required - **salt** (felt252) - Required - **order_key** (OrderKey) - Required - **token0** (address) - Required - **token1** (address) - Required - **tick** (i129) - Required - **mag** (u128) - Required - **sign** (bool) - Required ### Request Example ```cairo use ekubo::interfaces::extensions::limit_orders::{ ILimitOrdersDispatcher, GetOrderInfoRequest, OrderKey }; use ekubo::types::i129::i129; let limit_orders = ILimitOrdersDispatcher { contract_address: LIMIT_ORDERS_ADDRESS }; let request1 = GetOrderInfoRequest { ... }; // Define first request let request2 = GetOrderInfoRequest { ... }; // Define second request let results = limit_orders.get_order_infos(array![request1, request2].span()); ``` ### Response #### Success Response (200) - **results** (array) - An array of results, one for each request. - Each element is a GetOrderInfoResult object: - **executed** (bool) - True if the order has been fully filled. - **amount0** (u128) - Token0 amount to collect if closed now. - **amount1** (u128) - Token1 amount to collect if closed now. - **state** (OrderState) - The current state of the order. - **liquidity** (u128) - Deposited liquidity. #### Response Example ```json [ { "executed": true, "amount0": "...", "amount1": "...", "state": { "liquidity": "..." } }, // ... more results ] ``` ``` -------------------------------- ### liquidity_delta_to_amount_delta Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Computes the exact token0 and token1 amounts required for a given change in liquidity, considering the current and range prices (as sqrt_ratio). ```APIDOC ## `liquidity_delta_to_amount_delta` — token amounts for a liquidity change Given a change in liquidity and the current/range prices (as `sqrt_ratio`), computes the exact token0 and token1 amounts required (or returned). ### Parameters - `sqrt_ratio_current` (u256): The current square root of the price ratio. - `delta_liquidity` (i129): The change in liquidity. Positive for adding liquidity, negative for removing. - `sqrt_ratio_lower` (u256): The lower bound of the price range. - `sqrt_ratio_upper` (u256): The upper bound of the price range. ### Returns - `Delta` (struct): Contains `amount0` and `amount1`, representing the token amounts to deposit or withdraw. ### Example ```cairo use ekubo::math::liquidity::liquidity_delta_to_amount_delta; use ekubo::types::delta::Delta; use ekubo::types::i129::i129; // Current price sqrt_ratio = 2**128 (tick ≈ 0) let sqrt_ratio_current: u256 = 340282366920938463463374607431768211456_u256; let sqrt_ratio_lower: u256 = 300000000000000000000000000000000000000_u256; let sqrt_ratio_upper: u256 = 380000000000000000000000000000000000000_u256; // Add 10^18 liquidity let delta: Delta = liquidity_delta_to_amount_delta( sqrt_ratio_current, i129 { mag: 1000000000000000000_u128, sign: false }, // +liquidity sqrt_ratio_lower, sqrt_ratio_upper, ); // delta.amount0 > 0 → token0 to deposit // delta.amount1 > 0 → token1 to deposit // Remove liquidity let remove_delta: Delta = liquidity_delta_to_amount_delta( sqrt_ratio_current, i129 { mag: 1000000000000000000_u128, sign: true }, // -liquidity sqrt_ratio_lower, sqrt_ratio_upper, ); // Both amounts are negative → tokens returned to caller ``` ``` -------------------------------- ### Execute Token Swap with ICore::swap Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt Performs a token swap within a lock callback. Supports both exact-input and exact-output modes for tokens. `sqrt_ratio_limit` provides price protection. ```cairo use ekubo::interfaces::core::{ICoreDispatcher, ICoreDispatcherTrait, SwapParameters}; use ekubo::types::delta::Delta; use ekubo::types::i129::i129; use ekubo::math::ticks::constants::{MIN_SQRT_RATIO, MAX_SQRT_RATIO}; // Inside a locked callback: let core = ICoreDispatcher { contract_address: CORE_ADDRESS }; // Exact-input: sell 500 token1, receive as much token0 as possible let delta: Delta = core.swap( pool_key, SwapParameters { amount: i129 { mag: 500_u128, sign: false }, // positive = exact input is_token1: true, // amount denominated in token1 sqrt_ratio_limit: MIN_SQRT_RATIO, // price can drop freely skip_ahead: 0_u128, }, ); // delta.amount1 = +500 → 500 token1 owed to core (caller pays) // delta.amount0 < 0 → core owes token0 to caller (caller withdraws) // Exact-output: receive exactly 200 token0, pay as little token1 as required let delta2: Delta = core.swap( pool_key, SwapParameters { amount: i129 { mag: 200_u128, sign: true }, // negative = exact output is_token1: false, // output is token0 sqrt_ratio_limit: MIN_SQRT_RATIO, skip_ahead: 0_u128, }, ); ``` -------------------------------- ### Compute Swap Outcome in Cairo Source: https://context7.com/ekuboprotocol/starknet-contracts/llms.txt This function calculates the result of a swap against a constant-liquidity segment. It returns consumed input, output amounts, the next price, and fees collected. Ensure `MIN_SQRT_RATIO` is used as a price limit for safety. ```cairo use ekubo::math::swap::{swap_result, SwapResult}; use ekubo::types::i129::i129; use ekubo::math::ticks::constants::MIN_SQRT_RATIO; let sqrt_ratio: u256 = 340282366920938463463374607431768211456_u256; // current price let liquidity: u128 = 5000000000000000000_u128; let fee: u128 = 1701411834604692317316873037158841057280_u128; // 0.5% // Exact-input: swap 1000 token0 (positive amount, not token1) let result: SwapResult = swap_result( sqrt_ratio, liquidity, MIN_SQRT_RATIO, // price limit i129 { mag: 1000_u128, sign: false }, // exact input 1000 false, // is_token1 = false → amount in token0 fee, ); // result.consumed_amount — how much of the 1000 was actually used // result.calculated_amount — token1 output // result.sqrt_ratio_next — new pool price // result.fee_amount — fees collected ```