Swap and Preswap

1. Swap

Function params

  • pool: one mutable reference of the pool.

  • coins_a: vector of coin a. this type is the same as the coin a of pool.

  • coins_b: vector of coin b. this type is the same as the coin b of pool.

  • a2b: the swap direction, a2b equals true means sold coin a then get coin b.

  • by_amount_in: when it equal true means want to fix the amount of input coin. when it equal false means want to fix the amount of output coin.

  • amount: when by_amount_in equals true, amount means the quantity of input coin, when by_amount_in equals false, amount means the quantity of output coin.

  • amount_limit: the threshold value of coin. when by_amount_in equals true, it means the minimum amount about received coin, when by_amount_in equals false, it means the maximum amount abount sold.

  • sqrt_price_limit: two constant of sqrt price(x64 fixed-point number). When a2b equals true, it equals 4295048016, when a2b equals false, it equals 79226673515401279992447579055.

  • clock: the sui clock object.

You can implement swaps like the following example.

// Swap
fun swap<CoinTypeA, CoinTypeB>(
    config: &GlobalConfig,
    pool: &mut Pool<CoinTypeA, CoinTypeB>,
    coins_a: vector<Coin<CoinTypeA>>,
    coins_b: vector<Coin<CoinTypeB>>,
    a2b: bool,
    by_amount_in: bool,
    amount: u64,
    amount_limit: u64,
    sqrt_price_limit: u128,
    clock: &Clock,
    ctx: &mut TxContext
) {
    let (coin_a, coin_b) = (merge_coins(coins_a, ctx), merge_coins(coins_b, ctx));
    let (receive_a, receive_b, flash_receipt) = pool::flash_swap<CoinTypeA, CoinTypeB>(
        config,
        pool,
        a2b,
        by_amount_in,
        amount,
        sqrt_price_limit,
        clock
    );
    let (in_amount, out_amount) = (
        pool::swap_pay_amount(&flash_receipt),
        if (a2b) balance::value(&receive_b) else balance::value(&receive_a)
    );

    // pay for flash swap
    let (pay_coin_a, pay_coin_b) = if (a2b) {
        (coin::into_balance(coin::split(&mut coin_a, in_amount, ctx)), balance::zero<CoinTypeB>())
    } else {
        (balance::zero<CoinTypeA>(), coin::into_balance(coin::split(&mut coin_b, in_amount, ctx)))
    };

    coin::join(&mut coin_b, coin::from_balance(receive_b, ctx));
    coin::join(&mut coin_a, coin::from_balance(receive_a, ctx));

    pool::repay_flash_swap<CoinTypeA, CoinTypeB>(
        config,
        pool,
        pay_coin_a,
        pay_coin_b,
        flash_receipt
    );

    // ... send coins

}

/// Swap with partner.
fun swap_with_partner<CoinTypeA, CoinTypeB>(
    config: &GlobalConfig,
    pool: &mut Pool<CoinTypeA, CoinTypeB>,
    partner: &mut Partner,
    coins_a: vector<Coin<CoinTypeA>>,
    coins_b: vector<Coin<CoinTypeB>>,
    a2b: bool,
    by_amount_in: bool,
    amount: u64,
    amount_limit: u64,
    sqrt_price_limit: u128,
    clock: &Clock,
    ctx: &mut TxContext
) {
    let (coin_a, coin_b) = (merge_coins(coins_a, ctx), merge_coins(coins_b, ctx));
    let (receive_a, receive_b, flash_receipt) = pool::flash_swap_with_partner<CoinTypeA, CoinTypeB>(
        config,
        pool,
        partner,
        a2b,
        by_amount_in,
        amount,
        sqrt_price_limit,
        clock
    );
    let (in_amount, out_amount) = (
        pool::swap_pay_amount(&flash_receipt),
        if (a2b) balance::value(&receive_b) else balance::value(&receive_a)
    );

    // pay for flash swap
    let (pay_coin_a, pay_coin_b) = if (a2b) {
        (coin::into_balance(coin::split(&mut coin_a, in_amount, ctx)), balance::zero<CoinTypeB>())
    } else {
        (balance::zero<CoinTypeA>(), coin::into_balance(coin::split(&mut coin_b, in_amount, ctx)))
    };

    coin::join(&mut coin_b, coin::from_balance(receive_b, ctx));
    coin::join(&mut coin_a, coin::from_balance(receive_a, ctx));

    pool::repay_flash_swap_with_partner<CoinTypeA, CoinTypeB>(
        config,
        pool,
        partner,
        pay_coin_a,
        pay_coin_b,
        flash_receipt
    );

    // ... send coins

}

2. Swap a to b

The details of params can see in swap part.

public entry fun swap_a2b<CoinTypeA, CoinTypeB>(
    config: &GlobalConfig,
    pool: &mut Pool<CoinTypeA, CoinTypeB>,
    coins_a: vector<Coin<CoinTypeA>>,
    by_amount_in: bool,
    amount: u64,
    amount_limit: u64,
    sqrt_price_limit: u128,
    clock: &Clock,
    ctx: &mut TxContext
) {
    swap(
        config,
        pool,
        coins_a,
        vector::empty(),
        true,
        by_amount_in,
        amount,
        amount_limit,
        sqrt_price_limit,
        clock,
        ctx
    );
}

3. Swap b to a

The details of params can see in swap part.

public entry fun swap_b2a<CoinTypeA, CoinTypeB>(
    config: &GlobalConfig,
    pool: &mut Pool<CoinTypeA, CoinTypeB>,
    coins_b: vector<Coin<CoinTypeB>>,
    by_amount_in: bool,
    amount: u64,
    amount_limit: u64,
    sqrt_price_limit: u128,
    clock: &Clock,
    ctx: &mut TxContext
) {
    swap(
        config,
        pool,
        vector::empty(),
        coins_b,
        false,
        by_amount_in,
        amount,
        amount_limit,
        sqrt_price_limit,
        clock,
        ctx
    );
}

4. Swap a to b with partner

The details of params can see in swap part.

public entry fun swap_a2b_with_partner<CoinTypeA, CoinTypeB>(
    config: &GlobalConfig,
    pool: &mut Pool<CoinTypeA, CoinTypeB>,
    partner: &mut Partner,
    coins_a: vector<Coin<CoinTypeA>>,
    by_amount_in: bool,
    amount: u64,
    amount_limit: u64,
    sqrt_price_limit: u128,
    clock: &Clock,
    ctx: &mut TxContext
) {
    swap_with_partner(
        config,
        pool,
        partner,
        coins_a,
        vector::empty(),
        true,
        by_amount_in,
        amount,
        amount_limit,
        sqrt_price_limit,
        clock,
        ctx
    );
}

5. Swap b to a with partner

The details of params can see in swap part.

public entry fun swap_b2a_with_partner<CoinTypeA, CoinTypeB>(
    config: &GlobalConfig,
    pool: &mut Pool<CoinTypeA, CoinTypeB>,
    partner: &mut Partner,
    coins_b: vector<Coin<CoinTypeB>>,
    by_amount_in: bool,
    amount: u64,
    amount_limit: u64,
    sqrt_price_limit: u128,
    clock: &Clock,
    ctx: &mut TxContext
) {
    swap_with_partner(
        config,
        pool,
        partner,
        vector::empty(),
        coins_b,
        false,
        by_amount_in,
        amount,
        amount_limit,
        sqrt_price_limit,
        clock,
        ctx
    );
}

6. Repay add liquidity

Function param

  • amount_limit_a: the max reply amount abount coinA.

  • amount_limit_b: the max reply amount abount coinB.

fun repay_add_liquidity<CoinTypeA, CoinTypeB>(
    config: &GlobalConfig,
    pool: &mut Pool<CoinTypeA, CoinTypeB>,
    receipt: AddLiquidityReceipt<CoinTypeA, CoinTypeB>,
    coins_a: vector<Coin<CoinTypeA>>,
    coins_b: vector<Coin<CoinTypeB>>,
    amount_limit_a: u64,
    amount_limit_b: u64,
    ctx: &mut TxContext
) {
    let (amount_need_a, amount_need_b) = pool::add_liquidity_pay_amount(&receipt);

    // let (balance_a, balance_b) = (
    //     coin::into_balance(coin::split(&mut coin_a, amount_need_a, ctx)),
    //     coin::into_balance(coin::split(&mut coin_b, amount_need_b, ctx)),
    // );

    pool::repay_add_liquidity(config, pool, balance_a, balance_b, receipt);

    // ...

}

7. Pre swap clmmpool/sources/pool

/// The step swap result
struct SwapStepResult has copy, drop, store {
    current_sqrt_price: u128,
    target_sqrt_price: u128,
    current_liquidity: u128,
    amount_in: u64,
    amount_out: u64,
    fee_amount: u64,
    remainer_amount: u64
}

/// The calculated swap result
struct CalculatedSwapResult has copy, drop, store {
    amount_in: u64,
    amount_out: u64,
    fee_amount: u64,
    fee_rate: u64,
    after_sqrt_price: u128,
    is_exceed: bool,
    step_results: vector<SwapStepResult>
}
// Calculate Swap Result

public fun calculate_swap_result<CoinTypeA, CoinTypeB>(
    pool: &Pool<CoinTypeA, CoinTypeB>,
    a2b: bool,
    by_amount_in: bool,
    amount: u64,
): CalculatedSwapResult {}

Last updated