fn claim_redeem_stake_batch_receipts(&mut self, account: &mut Account) -> bool {
        fn claim_redeemed_stake_for_batch(
            contract: &mut Contract,
            account: &mut Account,
            account_batch: domain::RedeemStakeBatch,
            mut receipt: domain::RedeemStakeBatchReceipt,
        ) {
            // how much STAKE did the account redeem in the batch
            let redeemed_stake = account_batch.balance().amount();

            // claim the NEAR tokens for the account
            let near = receipt.stake_token_value().stake_to_near(redeemed_stake);
            account.apply_near_credit(near);

            // track that the NEAR tokens were claimed
            receipt.stake_tokens_redeemed(redeemed_stake);
            if receipt.all_claimed() {
                // then delete the receipt and free the storage
                contract
                    .redeem_stake_batch_receipts
                    .remove(&account_batch.id());
            } else {
                contract
                    .redeem_stake_batch_receipts
                    .insert(&account_batch.id(), &receipt);
            }
        }

        /// for a pending withdrawal, funds can also be claimed against the liquidity pool
        fn claim_redeemed_stake_for_batch_pending_withdrawal(
            contract: &mut Contract,
            account: &mut Account,
            account_batch: &mut domain::RedeemStakeBatch,
            mut receipt: domain::RedeemStakeBatchReceipt,
        ) {
            // how much STAKE did the account redeem in the batch
            let redeemed_stake = account_batch.balance().amount();

            let redeemed_stake_near_value =
                receipt.stake_token_value().stake_to_near(redeemed_stake);
            let claimed_near = if contract.near_liquidity_pool >= redeemed_stake_near_value {
                redeemed_stake_near_value
            } else {
                contract.near_liquidity_pool
            };
            let redeemable_stake = receipt.stake_token_value().near_to_stake(claimed_near);
            account_batch.remove(redeemable_stake);

            // claim the STAKE tokens for the account
            // let near = receipt.stake_token_value().stake_to_near(redeemable_stake);
            account.apply_near_credit(claimed_near);
            contract.near_liquidity_pool -= claimed_near;
            contract.total_near.credit(claimed_near);

            // track that the STAKE tokens were claimed
            receipt.stake_tokens_redeemed(redeemable_stake);
            if receipt.all_claimed() {
                // this means that effectively all funds have been withdrawn
                // which means we need to finalize the redeem workflow
                contract
                    .redeem_stake_batch_receipts
                    .remove(&account_batch.id());
                contract.redeem_stake_batch_lock = None;
                contract.pop_redeem_stake_batch();
            } else {
                contract
                    .redeem_stake_batch_receipts
                    .insert(&account_batch.id(), &receipt);
            }
        }

        let mut claimed_funds = false;

        match self.redeem_stake_batch_lock {
            // NEAR funds can be claimed for receipts that are not pending on the unstaked NEAR withdrawal
            // NEAR funds can also be claimed against the NEAR liquidity pool
            Some(RedeemLock::PendingWithdrawal) => {
                // NEAR funds cannot be claimed for a receipt that is pending withdrawal of unstaked NEAR from the staking pool
                let pending_batch_id = self
                    .redeem_stake_batch
                    .expect(REDEEM_STAKE_BATCH_SHOULD_EXIST)
                    .id();

                if let Some(mut batch) = account.redeem_stake_batch {
                    if batch.id() != pending_batch_id {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch(self, account, batch, receipt);
                            account.redeem_stake_batch = None;
                            claimed_funds = true;
                        }
                    } else if self.near_liquidity_pool.value() > 0 {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch_pending_withdrawal(
                                self, account, &mut batch, receipt,
                            );
                            if batch.balance().amount().value() == 0 {
                                account.redeem_stake_batch = None;
                            } else {
                                account.redeem_stake_batch = Some(batch);
                            }
                            claimed_funds = true;
                        }
                    }
                }

                if let Some(mut batch) = account.next_redeem_stake_batch {
                    if batch.id() != pending_batch_id {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch(self, account, batch, receipt);
                            account.next_redeem_stake_batch = None;
                            claimed_funds = true;
                        }
                    } else if self.near_liquidity_pool.value() > 0 {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch_pending_withdrawal(
                                self, account, &mut batch, receipt,
                            );
                            if batch.balance().amount().value() == 0 {
                                account.next_redeem_stake_batch = None;
                            } else {
                                account.next_redeem_stake_batch = Some(batch);
                            }
                            claimed_funds = true;
                        }
                    }
                }
            }
            None => {
                if let Some(batch) = account.redeem_stake_batch {
                    if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                        claim_redeemed_stake_for_batch(self, account, batch, receipt);
                        account.redeem_stake_batch = None;
                        claimed_funds = true;
                    }
                }

                if let Some(batch) = account.next_redeem_stake_batch {
                    if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                        claim_redeemed_stake_for_batch(self, account, batch, receipt);
                        account.next_redeem_stake_batch = None;
                        claimed_funds = true;
                    }
                }
            }
            Some(_) => {
                // this should never be reachable
                // while unstaking STAKE balances need to be locked, which means no receipts should be claimed
                return false;
            }
        }

        // shift the next batch into the current batch if the funds have been claimed for the current batch
        // and if the contract is not locked because it is running redeem stake batch workflow.
        //
        // NOTE: while a contract is locked, all redeem requests must be collected in the next batch
        if self.redeem_stake_batch_lock.is_none() && account.redeem_stake_batch.is_none() {
            account.redeem_stake_batch = account.next_redeem_stake_batch.take();
        }

        claimed_funds
    }
/// claim NEAR tokens for redeeming STAKE
claim NEAR tokens for redeeming STAKE
claim NEAR tokens for redeeming STAKE
fn claim_redeem_stake_batch_receipts(&mut self, account: &mut Account) -> bool {
        fn claim_redeemed_stake_for_batch(
            contract: &mut Contract,
            account: &mut Account,
            account_batch: domain::RedeemStakeBatch,
            mut receipt: domain::RedeemStakeBatchReceipt,
        ) {
            // how much STAKE did the account redeem in the batch
            let redeemed_stake = account_batch.balance().amount();
            // claim the NEAR tokens for the account
            let near = receipt.stake_token_value().stake_to_near(redeemed_stake);
            account.apply_near_credit(near);
            // track that the NEAR tokens were claimed
            receipt.stake_tokens_redeemed(redeemed_stake);
            if receipt.all_claimed() {
                // then delete the receipt and free the storage
                contract
                    .redeem_stake_batch_receipts
                    .remove(&account_batch.id());
            } else {
                contract
                    .redeem_stake_batch_receipts
                    .insert(&account_batch.id(), &receipt);
            }
        }
        /// for a pending withdrawal, funds can also be claimed against the liquidity pool
        fn claim_redeemed_stake_for_batch_pending_withdrawal(
            contract: &mut Contract,
            account: &mut Account,
            account_batch: &mut domain::RedeemStakeBatch,
            mut receipt: domain::RedeemStakeBatchReceipt,
        ) {
            // how much STAKE did the account redeem in the batch
            let redeemed_stake = account_batch.balance().amount();
            let redeemed_stake_near_value =
                receipt.stake_token_value().stake_to_near(redeemed_stake);
            let claimed_near = if contract.near_liquidity_pool >= redeemed_stake_near_value {
                redeemed_stake_near_value
            } else {
                contract.near_liquidity_pool
            };
            let redeemable_stake = receipt.stake_token_value().near_to_stake(claimed_near);
            account_batch.remove(redeemable_stake);
            // claim the STAKE tokens for the account
            // let near = receipt.stake_token_value().stake_to_near(redeemable_stake);
            account.apply_near_credit(claimed_near);
            contract.near_liquidity_pool -= claimed_near;
            contract.total_near.credit(claimed_near);
            // track that the STAKE tokens were claimed
            receipt.stake_tokens_redeemed(redeemable_stake);
            if receipt.all_claimed() {
                // this means that effectively all funds have been withdrawn
                // which means we need to finalize the redeem workflow
                contract
                    .redeem_stake_batch_receipts
                    .remove(&account_batch.id());
                contract.redeem_stake_batch_lock = None;
                contract.pop_redeem_stake_batch();
            } else {
                contract
                    .redeem_stake_batch_receipts
                    .insert(&account_batch.id(), &receipt);
            }
        }
        let mut claimed_funds = false;
        match self.redeem_stake_batch_lock {
            // NEAR funds can be claimed for receipts that are not pending on the unstaked NEAR withdrawal
            // NEAR funds can also be claimed against the NEAR liquidity pool
            Some(RedeemLock::PendingWithdrawal) => {
                // NEAR funds cannot be claimed for a receipt that is pending withdrawal of unstaked NEAR from the staking pool
                let pending_batch_id = self
                    .redeem_stake_batch
                    .expect(REDEEM_STAKE_BATCH_SHOULD_EXIST)
                    .id();
                if let Some(mut batch) = account.redeem_stake_batch {
                    if batch.id() != pending_batch_id {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch(self, account, batch, receipt);
                            account.redeem_stake_batch = None;
                            claimed_funds = true;
                        }
                    } else if self.near_liquidity_pool.value() > 0 {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch_pending_withdrawal(
                                self, account, &mut batch, receipt,
                            );
                            if batch.balance().amount().value() == 0 {
                                account.redeem_stake_batch = None;
                            } else {
                                account.redeem_stake_batch = Some(batch);
                            }
                            claimed_funds = true;
                        }
                    }
                }
                if let Some(mut batch) = account.next_redeem_stake_batch {
                    if batch.id() != pending_batch_id {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch(self, account, batch, receipt);
                            account.next_redeem_stake_batch = None;
                            claimed_funds = true;
                        }
                    } else if self.near_liquidity_pool.value() > 0 {
                        if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                            claim_redeemed_stake_for_batch_pending_withdrawal(
                                self, account, &mut batch, receipt,
                            );
                            if batch.balance().amount().value() == 0 {
                                account.next_redeem_stake_batch = None;
                            } else {
                                account.next_redeem_stake_batch = Some(batch);
                            }
                            claimed_funds = true;
                        }
                    }
                }
            }
            None => {
                if let Some(batch) = account.redeem_stake_batch {
                    if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                        claim_redeemed_stake_for_batch(self, account, batch, receipt);
                        account.redeem_stake_batch = None;
                        claimed_funds = true;
                    }
                }
                if let Some(batch) = account.next_redeem_stake_batch {
                    if let Some(receipt) = self.redeem_stake_batch_receipts.get(&batch.id()) {
                        claim_redeemed_stake_for_batch(self, account, batch, receipt);
                        account.next_redeem_stake_batch = None;
                        claimed_funds = true;
                    }
                }
            }
            Some(_) => {
                // this should never be reachable
                // while unstaking STAKE balances need to be locked, which means no receipts should be claimed
                return false;
            }
        }
        // shift the next batch into the current batch if the funds have been claimed for the current batch
        // and if the contract is not locked because it is running redeem stake batch workflow.
        //
        // NOTE: while a contract is locked, all redeem requests must be collected in the next batch
        if self.redeem_stake_batch_lock.is_none() && account.redeem_stake_batch.is_none() {
            account.redeem_stake_batch = account.next_redeem_stake_batch.take();
        }
        claimed_funds
    }
fn claim_redeem_stake_batch_receipts ( & mut self , account : & mut Account ) -> bool { fn claim_redeemed_stake_for_batch ( contract : & mut Contract , account : & mut Account , account_batch : domain :: RedeemStakeBatch , mut receipt : domain :: RedeemStakeBatchReceipt , ) { // how much STAKE did the account redeem in the batch let redeemed_stake = account_batch . balance ( ) . amount ( ) ; // claim the NEAR tokens for the account let near = receipt . stake_token_value ( ) . stake_to_near ( redeemed_stake ) ; account . apply_near_credit ( near ) ; // track that the NEAR tokens were claimed receipt . stake_tokens_redeemed ( redeemed_stake ) ; if receipt . all_claimed ( ) { // then delete the receipt and free the storage contract . redeem_stake_batch_receipts . remove ( & account_batch . id ( ) ) ; } else { contract . redeem_stake_batch_receipts . insert ( & account_batch . id ( ) , & receipt ) ; } } /// for a pending withdrawal, funds can also be claimed against the liquidity pool fn claim_redeemed_stake_for_batch_pending_withdrawal ( contract : & mut Contract , account : & mut Account , account_batch : & mut domain :: RedeemStakeBatch , mut receipt : domain :: RedeemStakeBatchReceipt , ) { // how much STAKE did the account redeem in the batch let redeemed_stake = account_batch . balance ( ) . amount ( ) ; let redeemed_stake_near_value = receipt . stake_token_value ( ) . stake_to_near ( redeemed_stake ) ; let claimed_near = if contract . near_liquidity_pool >= redeemed_stake_near_value { redeemed_stake_near_value } else { contract . near_liquidity_pool } ; let redeemable_stake = receipt . stake_token_value ( ) . near_to_stake ( claimed_near ) ; account_batch . remove ( redeemable_stake ) ; // claim the STAKE tokens for the account // let near = receipt.stake_token_value().stake_to_near(redeemable_stake); account . apply_near_credit ( claimed_near ) ; contract . near_liquidity_pool -= claimed_near ; contract . total_near . credit ( claimed_near ) ; // track that the STAKE tokens were claimed receipt . stake_tokens_redeemed ( redeemable_stake ) ; if receipt . all_claimed ( ) { // this means that effectively all funds have been withdrawn // which means we need to finalize the redeem workflow contract . redeem_stake_batch_receipts . remove ( & account_batch . id ( ) ) ; contract . redeem_stake_batch_lock = None ; contract . pop_redeem_stake_batch ( ) ; } else { contract . redeem_stake_batch_receipts . insert ( & account_batch . id ( ) , & receipt ) ; } } let mut claimed_funds = false ; match self . redeem_stake_batch_lock { // NEAR funds can be claimed for receipts that are not pending on the unstaked NEAR withdrawal // NEAR funds can also be claimed against the NEAR liquidity pool Some ( RedeemLock :: PendingWithdrawal ) => { // NEAR funds cannot be claimed for a receipt that is pending withdrawal of unstaked NEAR from the staking pool let pending_batch_id = self . redeem_stake_batch . expect ( REDEEM_STAKE_BATCH_SHOULD_EXIST ) . id ( ) ; if let Some ( mut batch ) = account . redeem_stake_batch { if batch . id ( ) != pending_batch_id { if let Some ( receipt ) = self . redeem_stake_batch_receipts . get ( & batch . id ( ) ) { claim_redeemed_stake_for_batch ( self , account , batch , receipt ) ; account . redeem_stake_batch = None ; claimed_funds = true ; } } else if self . near_liquidity_pool . value ( ) > 0 { if let Some ( receipt ) = self . redeem_stake_batch_receipts . get ( & batch . id ( ) ) { claim_redeemed_stake_for_batch_pending_withdrawal ( self , account , & mut batch , receipt , ) ; if batch . balance ( ) . amount ( ) . value ( ) == 0 { account . redeem_stake_batch = None ; } else { account . redeem_stake_batch = Some ( batch ) ; } claimed_funds = true ; } } } if let Some ( mut batch ) = account . next_redeem_stake_batch { if batch . id ( ) != pending_batch_id { if let Some ( receipt ) = self . redeem_stake_batch_receipts . get ( & batch . id ( ) ) { claim_redeemed_stake_for_batch ( self , account , batch , receipt ) ; account . next_redeem_stake_batch = None ; claimed_funds = true ; } } else if self . near_liquidity_pool . value ( ) > 0 { if let Some ( receipt ) = self . redeem_stake_batch_receipts . get ( & batch . id ( ) ) { claim_redeemed_stake_for_batch_pending_withdrawal ( self , account , & mut batch , receipt , ) ; if batch . balance ( ) . amount ( ) . value ( ) == 0 { account . next_redeem_stake_batch = None ; } else { account . next_redeem_stake_batch = Some ( batch ) ; } claimed_funds = true ; } } } } None => { if let Some ( batch ) = account . redeem_stake_batch { if let Some ( receipt ) = self . redeem_stake_batch_receipts . get ( & batch . id ( ) ) { claim_redeemed_stake_for_batch ( self , account , batch , receipt ) ; account . redeem_stake_batch = None ; claimed_funds = true ; } } if let Some ( batch ) = account . next_redeem_stake_batch { if let Some ( receipt ) = self . redeem_stake_batch_receipts . get ( & batch . id ( ) ) { claim_redeemed_stake_for_batch ( self , account , batch , receipt ) ; account . next_redeem_stake_batch = None ; claimed_funds = true ; } } } Some ( _ ) => { // this should never be reachable // while unstaking STAKE balances need to be locked, which means no receipts should be claimed return false ; } } // shift the next batch into the current batch if the funds have been claimed for the current batch // and if the contract is not locked because it is running redeem stake batch workflow. // // NOTE: while a contract is locked, all redeem requests must be collected in the next batch if self . redeem_stake_batch_lock . is_none ( ) && account . redeem_stake_batch . is_none ( ) { account . redeem_stake_batch = account . next_redeem_stake_batch . take ( ) ; } claimed_funds }
claim NEAR tokens for redeeming STAKE
claim NEAR tokens for redeeming STAKE
&mut self
account
&mut Account