UNPKG

@alcorexchange/alcor-swap-sdk

Version:

## Installation ​​ **npm** ``` npm i @alcorexchange/alcor-swap-sdk ``` **yarn** ``` yarn add @alcorexchange/alcor-swap-sdk ``` ## Usage ### Import:

580 lines (532 loc) 19.1 kB
import { Token } from "entities/token"; import { Percent } from "entities/fractions/percent"; import JSBI from "jsbi"; import { FeeAmount, TICK_SPACINGS } from "internalConstants"; import { encodeSqrtRatioX64 } from "utils/encodeSqrtRatioX64"; import { nearestUsableTick } from "utils/nearestUsableTick"; import { TickMath } from "utils/tickMath"; import { Pool } from "entities/pool"; import { Position } from "entities/position"; describe.skip("Position", () => { const USDC = new Token("contracta", 6, "USDC", "USD Coin"); const DAI = new Token("contractb", 18, "DAI", "DAI Stablecoin"); const POOL_SQRT_RATIO_START = encodeSqrtRatioX64(100e6, 100e18); const POOL_TICK_CURRENT = TickMath.getTickAtSqrtRatio(POOL_SQRT_RATIO_START); const TICK_SPACING = TICK_SPACINGS[FeeAmount.LOW]; const DAI_USDC_POOL = new Pool({ tokenA: DAI, tokenB: USDC, fee: FeeAmount.LOW, sqrtPriceX64: POOL_SQRT_RATIO_START, liquidity: 0, tickCurrent: POOL_TICK_CURRENT, ticks: [] }); it("can be constructed around 0 tick", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: -10, tickUpper: 10, }); expect(position.liquidity).toEqual(JSBI.BigInt(1)); }); it("can use min and max ticks", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: nearestUsableTick(TickMath.MIN_TICK, TICK_SPACING), tickUpper: nearestUsableTick(TickMath.MAX_TICK, TICK_SPACING), }); expect(position.liquidity).toEqual(JSBI.BigInt(1)); }); it("tick lower must be less than tick upper", () => { expect( () => new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: 10, tickUpper: -10, }) ).toThrow("TICK_ORDER"); }); it("tick lower cannot equal tick upper", () => { expect( () => new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: -10, tickUpper: -10, }) ).toThrow("TICK_ORDER"); }); it("tick lower must be multiple of tick spacing", () => { expect( () => new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: -5, tickUpper: 10, }) ).toThrow("TICK_LOWER"); }); it("tick lower must be greater than MIN_TICK", () => { expect( () => new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: nearestUsableTick(TickMath.MIN_TICK, TICK_SPACING) - TICK_SPACING, tickUpper: 10, }) ).toThrow("TICK_LOWER"); }); it("tick upper must be multiple of tick spacing", () => { expect( () => new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: -10, tickUpper: 15, }) ).toThrow("TICK_UPPER"); }); it("tick upper must be less than MAX_TICK", () => { expect( () => new Position({ pool: DAI_USDC_POOL, liquidity: 1, tickLower: -10, tickUpper: nearestUsableTick(TickMath.MAX_TICK, TICK_SPACING) + TICK_SPACING, }) ).toThrow("TICK_UPPER"); }); describe("#amountA", () => { it("is correct for price above", () => { expect( new Position({ pool: DAI_USDC_POOL, liquidity: 100e12, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }).amountA.quotient.toString() ).toEqual("49949961958869841"); }); it("is correct for price below", () => { expect( new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING, }).amountA.quotient.toString() ).toEqual("0"); }); it("is correct for in-range position", () => { expect( new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }).amountA.quotient.toString() ).toEqual("120054069145287995769396"); }); }); describe("#amountB", () => { it("is correct for price above", () => { expect( new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }).amountB.quotient.toString() ).toEqual("0"); }); it("is correct for price below", () => { expect( new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING, }).amountB.quotient.toString() ).toEqual("49970077052"); }); it("is correct for in-range position", () => { expect( new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }).amountB.quotient.toString() ).toEqual("79831926242"); }); }); describe("#mintAmountsWithSlippage", () => { describe("0 slippage", () => { const slippageTolerance = new Percent(0); it("is correct for positions below", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("49949961958869841738198"); expect(amountB.toString()).toEqual("0"); }); it("is correct for positions above", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("0"); expect(amountB.toString()).toEqual("49970077053"); }); it("is correct for positions within", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("120054069145287995740584"); expect(amountB.toString()).toEqual("79831926243"); }); }); describe(".05% slippage", () => { const slippageTolerance = new Percent(5, 10000); it("is correct for positions below", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("49949961958869841738198"); expect(amountB.toString()).toEqual("0"); }); it("is correct for positions above", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("0"); expect(amountB.toString()).toEqual("49970077053"); }); it("is correct for positions within", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("95063440240746211432007"); expect(amountB.toString()).toEqual("54828800461"); }); }); describe("5% slippage tolerance", () => { const slippageTolerance = new Percent(5, 100); it("is correct for pool at min price", () => { const position = new Position({ pool: new Pool({ tokenA: DAI, tokenB: USDC, fee: FeeAmount.LOW, sqrtPriceX64: TickMath.MIN_SQRT_RATIO, liquidity: 0, tickCurrent: TickMath.MIN_TICK, ticks: [] }), liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("49949961958869841754181"); expect(amountB.toString()).toEqual("0"); }); it("is correct for pool at max price", () => { const position = new Position({ pool: new Pool({ tokenA: DAI, tokenB: USDC, fee: FeeAmount.LOW, sqrtPriceX64: JSBI.subtract(TickMath.MAX_SQRT_RATIO, JSBI.BigInt(1)), liquidity: 0, tickCurrent: TickMath.MAX_TICK - 1, ticks: [] }), liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("0"); expect(amountB.toString()).toEqual("50045084659"); }); }); }); describe("#burnAmountsWithSlippage", () => { describe("0 slippage", () => { const slippageTolerance = new Percent(0); it("is correct for positions below", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("49949961958869841754181"); expect(amountB.toString()).toEqual("0"); }); it("is correct for positions above", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("0"); expect(amountB.toString()).toEqual("49970077052"); }); it("is correct for positions within", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("120054069145287995769396"); expect(amountB.toString()).toEqual("79831926242"); }); }); describe(".05% slippage", () => { const slippageTolerance = new Percent(5, 10000); it("is correct for positions below", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("49949961958869841754181"); expect(amountB.toString()).toEqual("0"); }); it("is correct for positions above", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("0"); expect(amountB.toString()).toEqual("49970077052"); }); it("is correct for positions within", () => { const position = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.burnAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("95063440240746211454822"); expect(amountB.toString()).toEqual("54828800460"); }); }); describe("5% slippage tolerance", () => { const slippageTolerance = new Percent(5, 100); it("is correct for pool at min price", () => { const position = new Position({ pool: new Pool({ tokenA: DAI, tokenB: USDC, fee: FeeAmount.LOW, sqrtPriceX64: TickMath.MIN_SQRT_RATIO, liquidity: 0, tickCurrent: TickMath.MIN_TICK, ticks: [] }), liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("49949961958869841738198"); expect(amountB.toString()).toEqual("0"); }); it("is correct for pool at max price", () => { const position = new Position({ pool: new Pool({ tokenA: DAI, tokenB: USDC, fee: FeeAmount.LOW, sqrtPriceX64: JSBI.subtract(TickMath.MAX_SQRT_RATIO, JSBI.BigInt(1)), liquidity: 0, tickCurrent: TickMath.MAX_TICK - 1, ticks: [] }), liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }); const { amountA, amountB } = position.mintAmountsWithSlippage(slippageTolerance); expect(amountA.toString()).toEqual("0"); expect(amountB.toString()).toEqual("50045084660"); }); }); }); describe("#mintAmounts", () => { it("is correct for price above", () => { const { amountA, amountB } = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }).mintAmounts; expect(amountA.toString()).toEqual("49949961958869841754182"); expect(amountB.toString()).toEqual("0"); }); it("is correct for price below", () => { const { amountA, amountB } = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING, }).mintAmounts; expect(amountA.toString()).toEqual("0"); expect(amountB.toString()).toEqual("49970077053"); }); it("is correct for in-range position", () => { const { amountA, amountB } = new Position({ pool: DAI_USDC_POOL, liquidity: 100e18, tickLower: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) - TICK_SPACING * 2, tickUpper: nearestUsableTick(POOL_TICK_CURRENT, TICK_SPACING) + TICK_SPACING * 2, }).mintAmounts; // note these are rounded up expect(amountA.toString()).toEqual("120054069145287995769397"); expect(amountB.toString()).toEqual("79831926243"); }); }); });