@@ -131,32 +131,74 @@ pub mod merkle_distributor {
131131 amount : u64 ,
132132 is_staked : bool , //true if staked, false if unstaked
133133 ) -> Result < ( ) > {
134+ // Check program ID
134135 let program_id = get_staking_caller ( & ctx. accounts . instruction ) ?;
135136 let staking_contract = ctx. accounts . distributor . staking_contract_address ;
136137 if program_id != staking_contract {
137- panic ! ( "Invalid program id " ) ;
138+ panic ! ( "Invalid program ID " ) ;
138139 }
140+
141+ // Get the current timestamp
139142 let current_ts = Clock :: get ( ) ?. unix_timestamp ;
140143 let claimer_status = & mut ctx. accounts . claim_status ;
144+
141145 if is_staked {
146+ // Handle staking: Add a new item to `staked_list`
142147 claimer_status. staked_list . push ( StakedItem {
143148 stake_amount : amount,
144149 stake_timestamp_start : Some ( current_ts) ,
145150 already_staked_duration_time : 0 ,
146151 } ) ;
147152 } else {
148- let curr_ts = Clock :: get ( ) ?. unix_timestamp ;
149- let mut _unstake_amount = 0 ;
150- for i in claimer_status. staked_list . iter_mut ( ) {
151- let Some ( stake_timestamp_start) = i. stake_timestamp_start else {
153+ // Handle unstaking: Process the required unstake amount
154+ let mut remaining_unstake_amount = amount;
155+
156+ // We need a new list to store updated staked items after partial unstaking
157+ let mut new_staked_item = None ;
158+
159+ for staked_item in claimer_status. staked_list . iter_mut ( ) {
160+ if remaining_unstake_amount == 0 {
161+ // If no more amount needs to be unstaked, keep the rest as-is
162+ break ;
163+ }
164+
165+ // Only process items that have a start timestamp (still staked)
166+ let Some ( stake_timestamp_start) = staked_item. stake_timestamp_start else {
152167 continue ;
153168 } ;
154- i. stake_timestamp_start = None ;
155- let diff = curr_ts. checked_sub ( stake_timestamp_start) . ok_or ( crate :: error:: ErrorCode :: ArithmeticError ) ?;
156- i. already_staked_duration_time = i. already_staked_duration_time . checked_add ( diff) . ok_or ( crate :: error:: ErrorCode :: ArithmeticError ) ?;
157- _unstake_amount += i. stake_amount ;
169+
170+ // Calculate time staked and update the duration
171+ let time_staked = current_ts. checked_sub ( stake_timestamp_start)
172+ . ok_or ( crate :: error:: ErrorCode :: ArithmeticError ) ?;
173+ staked_item. already_staked_duration_time = staked_item
174+ . already_staked_duration_time
175+ . checked_add ( time_staked)
176+ . ok_or ( crate :: error:: ErrorCode :: ArithmeticError ) ?;
177+
178+ if staked_item. stake_amount <= remaining_unstake_amount {
179+ // Fully unstake this item and update the remaining amount
180+ remaining_unstake_amount -= staked_item. stake_amount ;
181+ } else {
182+ // Partially unstake: Keep original as-is, and create a new item for unstaked portion
183+ new_staked_item = Some ( StakedItem {
184+ stake_amount : staked_item. stake_amount - remaining_unstake_amount,
185+ stake_timestamp_start : Some ( current_ts) , // New start time for remaining amount
186+ already_staked_duration_time : 0 ,
187+ } ) ;
188+
189+ // Adjust the original item to reflect the unstaked portion
190+ staked_item. stake_amount = remaining_unstake_amount;
191+ staked_item. stake_timestamp_start = None ;
192+ remaining_unstake_amount = 0 ;
193+ }
194+ }
195+
196+ if let Some ( new_item) = new_staked_item. clone ( ) {
197+ claimer_status. staked_list . push ( new_item) ;
158198 }
199+
159200 }
201+
160202 Ok ( ( ) )
161203 }
162204}
0 commit comments