pub fn compute_lp_amount_for_withdraw(
        &self,
        withdraw_c_amounts: &Vec<Balance>, // withdraw tokens in comparable precision,
        old_c_amounts: &Vec<Balance>, // in-pool tokens comparable amounts vector, 
        pool_token_supply: Balance, // total share supply
        fees: &Fees,
    ) -> Option<(Balance, Balance)> {
        let n_coins = old_c_amounts.len();
        // Initial invariant, D0
        let d_0 = self.compute_d(old_c_amounts)?;

        // real invariant after withdraw, D1
        let mut new_balances = vec![0_u128; n_coins];
        for (index, value) in withdraw_c_amounts.iter().enumerate() {
            new_balances[index] = old_c_amounts[index].checked_sub(*value)?;
        }

        let d_1 = self.compute_d(&new_balances)?;

        // compare ideal token portions from D1 with withdraws, to calculate diff fee.
        if d_1 >= d_0 {
            None
        } else {
            // Recalculate the invariant accounting for fees
            for i in 0..new_balances.len() {
                let ideal_balance = d_1
                    .checked_mul(old_c_amounts[i].into())?
                    .checked_div(d_0)?
                    .as_u128();
                let difference = if ideal_balance > new_balances[i] {
                    ideal_balance.checked_sub(new_balances[i])?
                } else {
                    new_balances[i].checked_sub(ideal_balance)?
                };
                let fee = fees.normalized_trade_fee(n_coins as u32, difference);
                // new_balance is for calculation D2, the one with fee charged
                new_balances[i] = new_balances[i].checked_sub(fee)?;
            }

            let d_2 = self.compute_d(&new_balances)?;

            // d0 > d1 > d2, 
            // (d0-d2) => burn_shares (plus fee),
            // (d0-d1) => diff_shares (without fee),
            // (d1-d2) => fee part,
            // burn_shares = diff_shares + fee part
            let burn_shares = U256::from(pool_token_supply)
                .checked_mul(d_0.checked_sub(d_2)?)?
                .checked_div(d_0)?
                .as_u128();
            let diff_shares = U256::from(pool_token_supply)
                .checked_mul(d_0.checked_sub(d_1)?)?
                .checked_div(d_0)?
                .as_u128();

            Some((burn_shares, burn_shares-diff_shares))
        }

    }
/// given token_out user want get and total tokens in pool and lp token supply,
/// return <lp_amount_to_burn, lp_fees_part>
/// all amounts are in c_amount (comparable amount)
given token_out user want get and total tokens in pool and lp token supply,
return 
all amounts are in c_amount (comparable amount)
given token_out user want get and total tokens in pool and lp token supply return all amounts are in c_amount ( comparable amount )
pub fn compute_lp_amount_for_withdraw(
        &self,
        withdraw_c_amounts: &Vec<Balance>, // withdraw tokens in comparable precision,
        old_c_amounts: &Vec<Balance>, // in-pool tokens comparable amounts vector, 
        pool_token_supply: Balance, // total share supply
        fees: &Fees,
    ) -> Option<(Balance, Balance)> {
        let n_coins = old_c_amounts.len();
        // Initial invariant, D0
        let d_0 = self.compute_d(old_c_amounts)?;
        // real invariant after withdraw, D1
        let mut new_balances = vec![0_u128; n_coins];
        for (index, value) in withdraw_c_amounts.iter().enumerate() {
            new_balances[index] = old_c_amounts[index].checked_sub(*value)?;
        }
        let d_1 = self.compute_d(&new_balances)?;
        // compare ideal token portions from D1 with withdraws, to calculate diff fee.
        if d_1 >= d_0 {
            None
        } else {
            // Recalculate the invariant accounting for fees
            for i in 0..new_balances.len() {
                let ideal_balance = d_1
                    .checked_mul(old_c_amounts[i].into())?
                    .checked_div(d_0)?
                    .as_u128();
                let difference = if ideal_balance > new_balances[i] {
                    ideal_balance.checked_sub(new_balances[i])?
                } else {
                    new_balances[i].checked_sub(ideal_balance)?
                };
                let fee = fees.normalized_trade_fee(n_coins as u32, difference);
                // new_balance is for calculation D2, the one with fee charged
                new_balances[i] = new_balances[i].checked_sub(fee)?;
            }
            let d_2 = self.compute_d(&new_balances)?;
            // d0 > d1 > d2, 
            // (d0-d2) => burn_shares (plus fee),
            // (d0-d1) => diff_shares (without fee),
            // (d1-d2) => fee part,
            // burn_shares = diff_shares + fee part
            let burn_shares = U256::from(pool_token_supply)
                .checked_mul(d_0.checked_sub(d_2)?)?
                .checked_div(d_0)?
                .as_u128();
            let diff_shares = U256::from(pool_token_supply)
                .checked_mul(d_0.checked_sub(d_1)?)?
                .checked_div(d_0)?
                .as_u128();
            Some((burn_shares, burn_shares-diff_shares))
        }
    }
pub fn compute_lp_amount_for_withdraw ( & self , withdraw_c_amounts : & Vec < Balance > , // withdraw tokens in comparable precision, old_c_amounts : & Vec < Balance > , // in-pool tokens comparable amounts vector,  pool_token_supply : Balance , // total share supply fees : & Fees , ) -> Option < ( Balance , Balance ) > { let n_coins = old_c_amounts . len ( ) ; // Initial invariant, D0 let d_0 = self . compute_d ( old_c_amounts ) ? ; // real invariant after withdraw, D1 let mut new_balances = vec ! [ 0_u128 n_coins ] ; for ( index , value ) in withdraw_c_amounts . iter ( ) . enumerate ( ) { new_balances [ index ] = old_c_amounts [ index ] . checked_sub ( * value ) ? ; } let d_1 = self . compute_d ( & new_balances ) ? ; // compare ideal token portions from D1 with withdraws, to calculate diff fee. if d_1 >= d_0 { None } else { // Recalculate the invariant accounting for fees for i in 0 .. new_balances . len ( ) { let ideal_balance = d_1 . checked_mul ( old_c_amounts [ i ] . into ( ) ) ? . checked_div ( d_0 ) ? . as_u128 ( ) ; let difference = if ideal_balance > new_balances [ i ] { ideal_balance . checked_sub ( new_balances [ i ] ) ? } else { new_balances [ i ] . checked_sub ( ideal_balance ) ? } ; let fee = fees . normalized_trade_fee ( n_coins as u32 , difference ) ; // new_balance is for calculation D2, the one with fee charged new_balances [ i ] = new_balances [ i ] . checked_sub ( fee ) ? ; } let d_2 = self . compute_d ( & new_balances ) ? ; // d0 > d1 > d2,  // (d0-d2) => burn_shares (plus fee), // (d0-d1) => diff_shares (without fee), // (d1-d2) => fee part, // burn_shares = diff_shares + fee part let burn_shares = U256 :: from ( pool_token_supply ) . checked_mul ( d_0 . checked_sub ( d_2 ) ? ) ? . checked_div ( d_0 ) ? . as_u128 ( ) ; let diff_shares = U256 :: from ( pool_token_supply ) . checked_mul ( d_0 . checked_sub ( d_1 ) ? ) ? . checked_div ( d_0 ) ? . as_u128 ( ) ; Some ( ( burn_shares , burn_shares - diff_shares ) ) } }
given token_out user want get and total tokens in pool and lp token supply,
return <lp_amount_to_burn, lp_fees_part>
all amounts are in c_amount (comparable amount)
given token_out user want get and total tokens in pool and lp token supply return <lp_amount_to_burn lp_fees_part > all amounts are in c_amount ( comparable amount )
&self
withdraw_c_amounts
&Vec<Balance>
old_c_amounts
&Vec<Balance>
pool_token_supply
Balance
fees
&Fees
&self
withdraw_c_amounts
&Vec<Balance>
old_c_amounts
&Vec<Balance>
pool_token_supply
Balance
fees
&Fees