1 | package org.cardanofoundation.explorer.api.service.impl; | |
2 | ||
3 | import java.math.BigInteger; | |
4 | import java.sql.Timestamp; | |
5 | import java.time.Instant; | |
6 | import java.time.LocalDateTime; | |
7 | import java.time.ZoneOffset; | |
8 | import java.util.ArrayList; | |
9 | import java.util.Comparator; | |
10 | import java.util.Date; | |
11 | import java.util.List; | |
12 | import java.util.Map; | |
13 | import java.util.Objects; | |
14 | import java.util.function.Function; | |
15 | import java.util.stream.Collectors; | |
16 | ||
17 | import lombok.RequiredArgsConstructor; | |
18 | import lombok.extern.log4j.Log4j2; | |
19 | ||
20 | import org.springframework.data.domain.Page; | |
21 | import org.springframework.data.domain.PageImpl; | |
22 | import org.springframework.data.domain.Pageable; | |
23 | import org.springframework.data.domain.Sort; | |
24 | import org.springframework.stereotype.Service; | |
25 | ||
26 | import org.cardanofoundation.conversions.CardanoConverters; | |
27 | import org.cardanofoundation.explorer.api.common.enumeration.StakeRewardType; | |
28 | import org.cardanofoundation.explorer.api.common.enumeration.TxStatus; | |
29 | import org.cardanofoundation.explorer.api.exception.BusinessCode; | |
30 | import org.cardanofoundation.explorer.api.exception.FetchRewardException; | |
31 | import org.cardanofoundation.explorer.api.exception.NoContentException; | |
32 | import org.cardanofoundation.explorer.api.model.request.stake.StakeLifeCycleFilterRequest; | |
33 | import org.cardanofoundation.explorer.api.model.response.BaseFilterResponse; | |
34 | import org.cardanofoundation.explorer.api.model.response.stake.lifecycle.*; | |
35 | import org.cardanofoundation.explorer.api.projection.StakeHistoryProjection; | |
36 | import org.cardanofoundation.explorer.api.projection.StakeTxProjection; | |
37 | import org.cardanofoundation.explorer.api.repository.ledgersync.DelegationRepository; | |
38 | import org.cardanofoundation.explorer.api.repository.ledgersync.EpochParamRepository; | |
39 | import org.cardanofoundation.explorer.api.repository.ledgersync.RewardRepository; | |
40 | import org.cardanofoundation.explorer.api.repository.ledgersync.StakeAddressRepository; | |
41 | import org.cardanofoundation.explorer.api.repository.ledgersync.StakeDeRegistrationRepository; | |
42 | import org.cardanofoundation.explorer.api.repository.ledgersync.StakeRegistrationRepository; | |
43 | import org.cardanofoundation.explorer.api.repository.ledgersync.TxOutRepository; | |
44 | import org.cardanofoundation.explorer.api.repository.ledgersync.TxRepository; | |
45 | import org.cardanofoundation.explorer.api.repository.ledgersync.WithdrawalRepository; | |
46 | import org.cardanofoundation.explorer.api.repository.ledgersyncagg.AddressTxAmountRepository; | |
47 | import org.cardanofoundation.explorer.api.service.FetchRewardDataService; | |
48 | import org.cardanofoundation.explorer.api.service.StakeKeyLifeCycleService; | |
49 | import org.cardanofoundation.explorer.common.entity.enumeration.RewardType; | |
50 | import org.cardanofoundation.explorer.common.entity.ledgersync.EpochParam; | |
51 | import org.cardanofoundation.explorer.common.entity.ledgersync.StakeAddress; | |
52 | import org.cardanofoundation.explorer.common.entity.ledgersync.Tx; | |
53 | import org.cardanofoundation.explorer.common.exception.BusinessException; | |
54 | ||
55 | @Service | |
56 | @RequiredArgsConstructor | |
57 | @Log4j2 | |
58 | public class StakeKeyLifeCycleServiceImpl implements StakeKeyLifeCycleService { | |
59 | ||
60 | public static final String MIN_TIME = "1970-01-01 00:00:00"; | |
61 | private final DelegationRepository delegationRepository; | |
62 | private final StakeRegistrationRepository stakeRegistrationRepository; | |
63 | private final StakeDeRegistrationRepository stakeDeRegistrationRepository; | |
64 | private final StakeAddressRepository stakeAddressRepository; | |
65 | private final RewardRepository rewardRepository; | |
66 | private final WithdrawalRepository withdrawalRepository; | |
67 | private final AddressTxAmountRepository addressTxAmountRepository; | |
68 | private final TxOutRepository txOutRepository; | |
69 | private final FetchRewardDataService fetchRewardDataService; | |
70 | private final EpochParamRepository epochParamRepository; | |
71 | private final TxRepository txRepository; | |
72 | private final CardanoConverters cardanoConverters; | |
73 | ||
74 | @Override | |
75 | public StakeLifecycleResponse getStakeLifeCycle(String stakeKey) { | |
76 | StakeAddress stakeAddress = | |
77 | stakeAddressRepository | |
78 | .findByView(stakeKey) | |
79 |
1
1. lambda$getStakeLifeCycle$0 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeLifeCycle$0 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
80 |
1
1. getStakeLifeCycle : negated conditional → KILLED |
if (!fetchRewardDataService.checkRewardAvailable(stakeKey)) { |
81 | boolean fetchRewardResponse = fetchRewardDataService.fetchReward(stakeKey); | |
82 |
1
1. getStakeLifeCycle : negated conditional → NO_COVERAGE |
if (!fetchRewardResponse) { |
83 | throw new FetchRewardException(BusinessCode.FETCH_REWARD_ERROR); | |
84 | } | |
85 | } | |
86 | BigInteger totalOperatorReward = null; | |
87 | BigInteger totalDelegatorReward = null; | |
88 | Boolean hasReward = null; | |
89 | Boolean hasWithdrawal = null; | |
90 |
1
1. getStakeLifeCycle : negated conditional → KILLED |
if (Boolean.TRUE.equals(fetchRewardDataService.useKoios())) { |
91 | totalOperatorReward = | |
92 | rewardRepository | |
93 | .getTotalRewardByStakeAddressAndType(stakeAddress, RewardType.LEADER) | |
94 | .orElse(BigInteger.ZERO); | |
95 | totalDelegatorReward = | |
96 | rewardRepository | |
97 | .getTotalRewardByStakeAddressAndType(stakeAddress, RewardType.MEMBER) | |
98 | .orElse(BigInteger.ZERO); | |
99 | hasReward = rewardRepository.existsByAddr(stakeAddress); | |
100 | hasWithdrawal = withdrawalRepository.existsByAddr(stakeAddress); | |
101 | } | |
102 | ||
103 |
1
1. getStakeLifeCycle : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeLifeCycle → KILLED |
return StakeLifecycleResponse.builder() |
104 | .hasRegistration(stakeRegistrationRepository.existsByAddr(stakeAddress)) | |
105 | .hasDeRegistration(stakeDeRegistrationRepository.existsByAddr(stakeAddress)) | |
106 | .hasDelegation(delegationRepository.existsByAddress(stakeAddress)) | |
107 | .hashRewards(hasReward) | |
108 | .hasWithdrawal(hasWithdrawal) | |
109 | .totalOperatorRewards(totalOperatorReward) | |
110 | .totalDelegatorRewards(totalDelegatorReward) | |
111 | .build(); | |
112 | } | |
113 | ||
114 | @Override | |
115 | public BaseFilterResponse<StakeRegistrationFilterResponse> getStakeRegistrations( | |
116 | String stakeKey, StakeLifeCycleFilterRequest condition, Pageable pageable) { | |
117 | StakeAddress stakeAddress = | |
118 | stakeAddressRepository | |
119 | .findByView(stakeKey) | |
120 |
1
1. lambda$getStakeRegistrations$1 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeRegistrations$1 → KILLED |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
121 | Timestamp fromDate = Timestamp.valueOf(MIN_TIME); | |
122 | Timestamp toDate = | |
123 | Timestamp.from( | |
124 | LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).toInstant(ZoneOffset.UTC)); | |
125 |
1
1. getStakeRegistrations : negated conditional → KILLED |
if (Objects.nonNull(condition.getFromDate())) { |
126 | fromDate = Timestamp.from(condition.getFromDate().toInstant()); | |
127 | } | |
128 |
1
1. getStakeRegistrations : negated conditional → KILLED |
if (Objects.nonNull(condition.getToDate())) { |
129 | toDate = Timestamp.from(condition.getToDate().toInstant()); | |
130 | } | |
131 |
2
1. getStakeRegistrations : negated conditional → KILLED 2. getStakeRegistrations : negated conditional → KILLED |
if (Objects.nonNull(condition.getTxHash()) && condition.getTxHash().isBlank()) { |
132 |
1
1. getStakeRegistrations : removed call to org/cardanofoundation/explorer/api/model/request/stake/StakeLifeCycleFilterRequest::setTxHash → KILLED |
condition.setTxHash(null); |
133 | } | |
134 | Page<StakeHistoryProjection> stakeHistoryList = | |
135 | stakeRegistrationRepository.getStakeRegistrationsByAddress( | |
136 | stakeAddress, condition.getTxHash(), fromDate, toDate, pageable); | |
137 | var epochNoList = stakeHistoryList.stream().map(StakeHistoryProjection::getEpochNo).toList(); | |
138 | var epochParams = epochParamRepository.findByEpochNoIn(epochNoList); | |
139 | Map<Integer, BigInteger> epochNoDepositMap = | |
140 | epochParams.stream() | |
141 | .collect(Collectors.toMap(EpochParam::getEpochNo, EpochParam::getKeyDeposit)); | |
142 | var response = | |
143 | stakeHistoryList.map( | |
144 | item -> | |
145 |
1
1. lambda$getStakeRegistrations$2 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeRegistrations$2 → KILLED |
StakeRegistrationFilterResponse.builder() |
146 | .txHash(item.getTxHash()) | |
147 | .fee(item.getFee()) | |
148 | .deposit(epochNoDepositMap.get(item.getEpochNo()).longValue()) | |
149 | .time(item.getTime().toLocalDateTime()) | |
150 | .build()); | |
151 |
1
1. getStakeRegistrations : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeRegistrations → KILLED |
return new BaseFilterResponse<>(response); |
152 | } | |
153 | ||
154 | @Override | |
155 | public StakeRegistrationDetailResponse getStakeRegistrationDetail(String stakeKey, String hash) { | |
156 | StakeHistoryProjection stakeHistoryProjection = | |
157 | stakeRegistrationRepository | |
158 | .findByAddressAndTx(stakeKey, hash) | |
159 |
1
1. lambda$getStakeRegistrationDetail$3 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeRegistrationDetail$3 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.STAKE_REGISTRATION_NOT_FOUND)); |
160 | Long deposit = | |
161 | epochParamRepository | |
162 | .findKeyDepositByEpochNo(stakeHistoryProjection.getEpochNo()) | |
163 | .longValue(); | |
164 | BigInteger totalInput = | |
165 | txOutRepository | |
166 | .sumValueInputByTxAndStakeAddress(stakeHistoryProjection.getTxHash(), stakeKey) | |
167 | .orElse(BigInteger.ZERO); | |
168 |
2
1. getStakeRegistrationDetail : changed conditional boundary → KILLED 2. getStakeRegistrationDetail : negated conditional → KILLED |
boolean joinDepositPaid = totalInput.compareTo(BigInteger.ZERO) > BigInteger.ZERO.intValue(); |
169 |
1
1. getStakeRegistrationDetail : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeRegistrationDetail → KILLED |
return StakeRegistrationDetailResponse.builder() |
170 | .txHash(stakeHistoryProjection.getTxHash()) | |
171 | .fee(stakeHistoryProjection.getFee()) | |
172 | .deposit(deposit) | |
173 | .time(stakeHistoryProjection.getTime().toLocalDateTime()) | |
174 | .joinDepositPaid(joinDepositPaid) | |
175 | .build(); | |
176 | } | |
177 | ||
178 | @Override | |
179 | public BaseFilterResponse<StakeDelegationFilterResponse> getStakeDelegations( | |
180 | String stakeKey, StakeLifeCycleFilterRequest condition, Pageable pageable) { | |
181 | StakeAddress stakeAddress = | |
182 | stakeAddressRepository | |
183 | .findByView(stakeKey) | |
184 |
1
1. lambda$getStakeDelegations$4 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeDelegations$4 → KILLED |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
185 | Timestamp fromDate = Timestamp.valueOf(MIN_TIME); | |
186 | Timestamp toDate = | |
187 | Timestamp.from( | |
188 | LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).toInstant(ZoneOffset.UTC)); | |
189 |
1
1. getStakeDelegations : negated conditional → KILLED |
if (Objects.nonNull(condition.getFromDate())) { |
190 | fromDate = Timestamp.from(condition.getFromDate().toInstant()); | |
191 | } | |
192 |
1
1. getStakeDelegations : negated conditional → KILLED |
if (Objects.nonNull(condition.getToDate())) { |
193 | toDate = Timestamp.from(condition.getToDate().toInstant()); | |
194 | } | |
195 |
2
1. getStakeDelegations : negated conditional → SURVIVED 2. getStakeDelegations : negated conditional → KILLED |
if (Objects.nonNull(condition.getTxHash()) && condition.getTxHash().isBlank()) { |
196 |
1
1. getStakeDelegations : removed call to org/cardanofoundation/explorer/api/model/request/stake/StakeLifeCycleFilterRequest::setTxHash → SURVIVED |
condition.setTxHash(null); |
197 | } | |
198 | var response = | |
199 | delegationRepository.findDelegationByAddress( | |
200 | stakeAddress, condition.getTxHash(), fromDate, toDate, pageable); | |
201 |
1
1. getStakeDelegations : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeDelegations → KILLED |
return new BaseFilterResponse<>( |
202 | response.map( | |
203 | item -> | |
204 |
1
1. lambda$getStakeDelegations$5 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeDelegations$5 → KILLED |
StakeDelegationFilterResponse.builder() |
205 | .txHash(item.getTxHash()) | |
206 | .fee(item.getFee()) | |
207 | .time(item.getTime().toLocalDateTime()) | |
208 | .outSum(item.getOutSum()) | |
209 | .poolName(item.getPoolName()) | |
210 | .poolId(item.getPoolId()) | |
211 | .build())); | |
212 | } | |
213 | ||
214 | @Override | |
215 | public StakeDelegationDetailResponse getStakeDelegationDetail(String stakeKey, String hash) { | |
216 | StakeAddress stakeAddress = | |
217 | stakeAddressRepository | |
218 | .findByView(stakeKey) | |
219 |
1
1. lambda$getStakeDelegationDetail$6 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeDelegationDetail$6 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
220 | var delegation = | |
221 | delegationRepository | |
222 | .findDelegationByAddressAndTx(stakeAddress, hash) | |
223 |
1
1. lambda$getStakeDelegationDetail$7 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeDelegationDetail$7 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.STAKE_DELEGATION_NOT_FOUND)); |
224 | var totalBalance = | |
225 | addressTxAmountRepository | |
226 | .getBalanceByStakeAddressAndSlotAfter( | |
227 | stakeAddress.getView(), | |
228 | cardanoConverters.time().toSlot(delegation.getTime().toLocalDateTime())) | |
229 | .orElse(BigInteger.ZERO); | |
230 |
1
1. getStakeDelegationDetail : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeDelegationDetail → KILLED |
return StakeDelegationDetailResponse.builder() |
231 | .fee(delegation.getFee()) | |
232 | .outSum(delegation.getOutSum()) | |
233 | .poolId(delegation.getPoolId()) | |
234 | .poolName(delegation.getPoolData()) | |
235 | .time(delegation.getTime().toLocalDateTime()) | |
236 | .txHash(delegation.getTxHash()) | |
237 | .blockNo(delegation.getBlockNo()) | |
238 | .epoch(delegation.getEpochNo()) | |
239 | .stakeTotalAmount(totalBalance) | |
240 | .build(); | |
241 | } | |
242 | ||
243 | @Override | |
244 | public BaseFilterResponse<StakeRewardResponse> getStakeRewards( | |
245 | String stakeKey, Date fromDate, Date toDate, RewardType type, Pageable pageable) { | |
246 | StakeAddress stakeAddress = | |
247 | stakeAddressRepository | |
248 | .findByView(stakeKey) | |
249 |
1
1. lambda$getStakeRewards$8 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeRewards$8 → KILLED |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
250 |
1
1. getStakeRewards : negated conditional → KILLED |
if (Boolean.FALSE.equals(fetchRewardDataService.useKoios())) { |
251 |
1
1. getStakeRewards : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeRewards → KILLED |
return new BaseFilterResponse<>(); |
252 | } | |
253 | ||
254 |
1
1. getStakeRewards : negated conditional → KILLED |
if (!fetchRewardDataService.checkRewardAvailable(stakeKey)) { |
255 | boolean fetchRewardResponse = fetchRewardDataService.fetchReward(stakeKey); | |
256 |
1
1. getStakeRewards : negated conditional → KILLED |
if (!fetchRewardResponse) { |
257 | throw new FetchRewardException(BusinessCode.FETCH_REWARD_ERROR); | |
258 | } | |
259 | } | |
260 | Timestamp fromTime = Timestamp.valueOf(MIN_TIME); | |
261 | Timestamp toTime = | |
262 | Timestamp.from( | |
263 | LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).toInstant(ZoneOffset.UTC)); | |
264 |
1
1. getStakeRewards : negated conditional → KILLED |
if (Objects.nonNull(fromDate)) { |
265 | fromTime = Timestamp.from(fromDate.toInstant()); | |
266 | } | |
267 |
1
1. getStakeRewards : negated conditional → KILLED |
if (Objects.nonNull(toDate)) { |
268 | toTime = Timestamp.from(toDate.toInstant()); | |
269 | } | |
270 | var response = | |
271 | rewardRepository.findRewardByStake(stakeAddress, fromTime, toTime, type, pageable); | |
272 |
1
1. getStakeRewards : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeRewards → KILLED |
return new BaseFilterResponse<>(response); |
273 | } | |
274 | ||
275 | @Override | |
276 | public BaseFilterResponse<StakeWithdrawalFilterResponse> getStakeWithdrawals( | |
277 | String stakeKey, StakeLifeCycleFilterRequest condition, Pageable pageable) { | |
278 | StakeAddress stakeAddress = | |
279 | stakeAddressRepository | |
280 | .findByView(stakeKey) | |
281 |
1
1. lambda$getStakeWithdrawals$9 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeWithdrawals$9 → KILLED |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
282 |
1
1. getStakeWithdrawals : negated conditional → KILLED |
if (Boolean.FALSE.equals(fetchRewardDataService.useKoios())) { |
283 |
1
1. getStakeWithdrawals : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeWithdrawals → NO_COVERAGE |
return new BaseFilterResponse<>(); |
284 | } | |
285 | Timestamp fromDate = Timestamp.valueOf(MIN_TIME); | |
286 | Timestamp toDate = | |
287 | Timestamp.from( | |
288 | LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).toInstant(ZoneOffset.UTC)); | |
289 |
1
1. getStakeWithdrawals : negated conditional → KILLED |
if (Objects.nonNull(condition.getFromDate())) { |
290 | fromDate = Timestamp.from(condition.getFromDate().toInstant()); | |
291 | } | |
292 |
1
1. getStakeWithdrawals : negated conditional → KILLED |
if (Objects.nonNull(condition.getToDate())) { |
293 | toDate = Timestamp.from(condition.getToDate().toInstant()); | |
294 | } | |
295 |
2
1. getStakeWithdrawals : negated conditional → SURVIVED 2. getStakeWithdrawals : negated conditional → KILLED |
if (Objects.nonNull(condition.getTxHash()) && condition.getTxHash().isBlank()) { |
296 |
1
1. getStakeWithdrawals : removed call to org/cardanofoundation/explorer/api/model/request/stake/StakeLifeCycleFilterRequest::setTxHash → SURVIVED |
condition.setTxHash(null); |
297 | } | |
298 | var response = | |
299 | withdrawalRepository.getWithdrawalByAddress( | |
300 | stakeAddress, condition.getTxHash(), fromDate, toDate, pageable); | |
301 |
1
1. getStakeWithdrawals : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeWithdrawals → KILLED |
return new BaseFilterResponse<>( |
302 | response.map( | |
303 | item -> | |
304 |
1
1. lambda$getStakeWithdrawals$10 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeWithdrawals$10 → KILLED |
StakeWithdrawalFilterResponse.builder() |
305 | .txHash(item.getTxHash()) | |
306 | .fee(item.getFee()) | |
307 | .time(item.getTime().toLocalDateTime()) | |
308 | .value(item.getAmount()) | |
309 | .build())); | |
310 | } | |
311 | ||
312 | @Override | |
313 | public StakeWithdrawalDetailResponse getStakeWithdrawalDetail(String stakeKey, String hash) { | |
314 | StakeAddress stakeAddress = | |
315 | stakeAddressRepository | |
316 | .findByView(stakeKey) | |
317 |
1
1. lambda$getStakeWithdrawalDetail$11 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeWithdrawalDetail$11 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
318 |
1
1. getStakeWithdrawalDetail : negated conditional → KILLED |
if (!fetchRewardDataService.checkRewardAvailable(stakeKey)) { |
319 | boolean fetchRewardResponse = fetchRewardDataService.fetchReward(stakeKey); | |
320 |
1
1. getStakeWithdrawalDetail : negated conditional → KILLED |
if (!fetchRewardResponse) { |
321 | throw new FetchRewardException(BusinessCode.FETCH_REWARD_ERROR); | |
322 | } | |
323 | } | |
324 | var withdrawal = | |
325 | withdrawalRepository | |
326 | .getWithdrawalByAddressAndTx(stakeAddress, hash) | |
327 |
1
1. lambda$getStakeWithdrawalDetail$12 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeWithdrawalDetail$12 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.STAKE_WITHDRAWAL_NOT_FOUND)); |
328 | var totalBalance = | |
329 | addressTxAmountRepository | |
330 | .getBalanceByStakeAddressAndSlotAfter( | |
331 | stakeAddress.getView(), | |
332 | cardanoConverters.time().toSlot(withdrawal.getTime().toLocalDateTime())) | |
333 | .orElse(BigInteger.ZERO); | |
334 | BigInteger rewardAvailable = null; | |
335 | ||
336 |
1
1. getStakeWithdrawalDetail : negated conditional → KILLED |
if (Boolean.TRUE.equals(fetchRewardDataService.useKoios())) { |
337 | var totalReward = | |
338 | rewardRepository | |
339 | .getAvailableRewardByStakeAddressAndEpoch(stakeAddress, withdrawal.getEpochNo()) | |
340 | .orElse(BigInteger.ZERO); | |
341 | var totalWithdrawal = | |
342 | withdrawalRepository | |
343 | .sumByAddrAndTx(stakeAddress, withdrawal.getTxId()) | |
344 | .orElse(BigInteger.ZERO); | |
345 | rewardAvailable = totalReward.subtract(totalWithdrawal); | |
346 | } | |
347 |
1
1. getStakeWithdrawalDetail : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeWithdrawalDetail → KILLED |
return StakeWithdrawalDetailResponse.builder() |
348 | .fee(withdrawal.getFee()) | |
349 | .amount(withdrawal.getAmount()) | |
350 | .time(withdrawal.getTime().toLocalDateTime()) | |
351 | .txHash(withdrawal.getTxHash()) | |
352 | .stakeTotalAmount(totalBalance) | |
353 | .stakeRewardAvailable(rewardAvailable) | |
354 | .build(); | |
355 | } | |
356 | ||
357 | @Override | |
358 | public BaseFilterResponse<StakeRegistrationFilterResponse> getStakeDeRegistrations( | |
359 | String stakeKey, StakeLifeCycleFilterRequest condition, Pageable pageable) { | |
360 | StakeAddress stakeAddress = | |
361 | stakeAddressRepository | |
362 | .findByView(stakeKey) | |
363 |
1
1. lambda$getStakeDeRegistrations$13 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeDeRegistrations$13 → KILLED |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
364 | Timestamp fromDate = Timestamp.valueOf(MIN_TIME); | |
365 | Timestamp toDate = | |
366 | Timestamp.from( | |
367 | LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC).toInstant(ZoneOffset.UTC)); | |
368 |
1
1. getStakeDeRegistrations : negated conditional → KILLED |
if (Objects.nonNull(condition.getFromDate())) { |
369 | fromDate = Timestamp.from(condition.getFromDate().toInstant()); | |
370 | } | |
371 |
1
1. getStakeDeRegistrations : negated conditional → KILLED |
if (Objects.nonNull(condition.getToDate())) { |
372 | toDate = Timestamp.from(condition.getToDate().toInstant()); | |
373 | } | |
374 |
2
1. getStakeDeRegistrations : negated conditional → KILLED 2. getStakeDeRegistrations : negated conditional → KILLED |
if (Objects.nonNull(condition.getTxHash()) && condition.getTxHash().isBlank()) { |
375 |
1
1. getStakeDeRegistrations : removed call to org/cardanofoundation/explorer/api/model/request/stake/StakeLifeCycleFilterRequest::setTxHash → KILLED |
condition.setTxHash(null); |
376 | } | |
377 | Page<StakeHistoryProjection> stakeHistoryList = | |
378 | stakeDeRegistrationRepository.getStakeDeRegistrationsByAddress( | |
379 | stakeAddress, condition.getTxHash(), fromDate, toDate, pageable); | |
380 | var epochNoList = stakeHistoryList.stream().map(StakeHistoryProjection::getEpochNo).toList(); | |
381 | var epochParams = epochParamRepository.findByEpochNoIn(epochNoList); | |
382 | Map<Integer, BigInteger> epochNoDepositMap = | |
383 | epochParams.stream() | |
384 | .collect(Collectors.toMap(EpochParam::getEpochNo, EpochParam::getKeyDeposit)); | |
385 | var response = | |
386 | stakeHistoryList.map( | |
387 | item -> | |
388 |
1
1. lambda$getStakeDeRegistrations$14 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeDeRegistrations$14 → KILLED |
StakeRegistrationFilterResponse.builder() |
389 | .txHash(item.getTxHash()) | |
390 | .fee(item.getFee()) | |
391 | .deposit( | |
392 | epochNoDepositMap | |
393 | .get(item.getEpochNo()) | |
394 | .multiply(BigInteger.valueOf(-1L)) | |
395 | .longValue()) | |
396 | .time(item.getTime().toLocalDateTime()) | |
397 | .build()); | |
398 |
1
1. getStakeDeRegistrations : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeDeRegistrations → KILLED |
return new BaseFilterResponse<>(response); |
399 | } | |
400 | ||
401 | @Override | |
402 | public StakeRegistrationDetailResponse getStakeDeRegistrationDetail( | |
403 | String stakeKey, String hash) { | |
404 | StakeHistoryProjection stakeHistoryProjection = | |
405 | stakeDeRegistrationRepository | |
406 | .findByAddressAndTx(stakeKey, hash) | |
407 |
1
1. lambda$getStakeDeRegistrationDetail$15 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeDeRegistrationDetail$15 → KILLED |
.orElseThrow(() -> new BusinessException(BusinessCode.STAKE_DE_REGISTRATION_NOT_FOUND)); |
408 | Long deposit = | |
409 | epochParamRepository | |
410 | .findKeyDepositByEpochNo(stakeHistoryProjection.getEpochNo()) | |
411 | .multiply(BigInteger.valueOf(-1)) | |
412 | .longValue(); | |
413 | BigInteger totalOutput = | |
414 | txOutRepository | |
415 | .sumValueOutputByTxAndStakeAddress(stakeHistoryProjection.getTxHash(), stakeKey) | |
416 | .orElse(BigInteger.ZERO); | |
417 |
2
1. getStakeDeRegistrationDetail : negated conditional → KILLED 2. getStakeDeRegistrationDetail : changed conditional boundary → KILLED |
boolean joinDepositPaid = totalOutput.compareTo(BigInteger.ZERO) > BigInteger.ZERO.intValue(); |
418 |
1
1. getStakeDeRegistrationDetail : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeDeRegistrationDetail → KILLED |
return StakeRegistrationDetailResponse.builder() |
419 | .txHash(stakeHistoryProjection.getTxHash()) | |
420 | .fee(stakeHistoryProjection.getFee()) | |
421 | .deposit(deposit) | |
422 | .time(stakeHistoryProjection.getTime().toLocalDateTime()) | |
423 | .joinDepositPaid(joinDepositPaid) | |
424 | .build(); | |
425 | } | |
426 | ||
427 | @Override | |
428 | public BaseFilterResponse<StakeWalletActivityResponse> getStakeWalletActivities( | |
429 | String stakeKey, Pageable pageable) { | |
430 | StakeAddress stakeAddress = | |
431 | stakeAddressRepository | |
432 | .findByView(stakeKey) | |
433 |
1
1. lambda$getStakeWalletActivities$16 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeWalletActivities$16 → KILLED |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
434 | Page<StakeTxProjection> txAmountList = | |
435 | addressTxAmountRepository.findTxAndAmountByStake(stakeAddress.getView(), pageable); | |
436 | ||
437 |
1
1. getStakeWalletActivities : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeWalletActivities → KILLED |
return new BaseFilterResponse<>(txAmountList, getContentWalletActivityResponse(txAmountList)); |
438 | } | |
439 | ||
440 | private List<StakeWalletActivityResponse> getContentWalletActivityResponse( | |
441 | Page<StakeTxProjection> txAmountList) { | |
442 | List<StakeWalletActivityResponse> response = new ArrayList<>(); | |
443 | Map<String, Tx> txMap = | |
444 | txRepository | |
445 | .findAllByHashIn( | |
446 | txAmountList.getContent().stream() | |
447 | .map(StakeTxProjection::getTxHash) | |
448 | .collect(Collectors.toList())) | |
449 | .stream() | |
450 | .collect(Collectors.toMap(Tx::getHash, Function.identity())); | |
451 | ||
452 | txAmountList | |
453 | .getContent() | |
454 |
1
1. getContentWalletActivityResponse : removed call to java/util/List::forEach → KILLED |
.forEach( |
455 | item -> { | |
456 | StakeWalletActivityResponse stakeWalletActivity = new StakeWalletActivityResponse(); | |
457 |
1
1. lambda$getContentWalletActivityResponse$17 : removed call to org/cardanofoundation/explorer/api/model/response/stake/lifecycle/StakeWalletActivityResponse::setTxHash → KILLED |
stakeWalletActivity.setTxHash(item.getTxHash()); |
458 |
1
1. lambda$getContentWalletActivityResponse$17 : removed call to org/cardanofoundation/explorer/api/model/response/stake/lifecycle/StakeWalletActivityResponse::setAmount → KILLED |
stakeWalletActivity.setAmount(item.getAmount()); |
459 |
1
1. lambda$getContentWalletActivityResponse$17 : removed call to org/cardanofoundation/explorer/api/model/response/stake/lifecycle/StakeWalletActivityResponse::setTime → SURVIVED |
stakeWalletActivity.setTime( |
460 | LocalDateTime.ofInstant(Instant.ofEpochSecond(item.getTime()), ZoneOffset.UTC)); | |
461 |
1
1. lambda$getContentWalletActivityResponse$17 : negated conditional → SURVIVED |
if (Boolean.TRUE.equals(txMap.get(item.getTxHash()).getValidContract())) { |
462 |
1
1. lambda$getContentWalletActivityResponse$17 : removed call to org/cardanofoundation/explorer/api/model/response/stake/lifecycle/StakeWalletActivityResponse::setStatus → NO_COVERAGE |
stakeWalletActivity.setStatus(TxStatus.SUCCESS); |
463 | } else { | |
464 |
1
1. lambda$getContentWalletActivityResponse$17 : removed call to org/cardanofoundation/explorer/api/model/response/stake/lifecycle/StakeWalletActivityResponse::setStatus → SURVIVED |
stakeWalletActivity.setStatus(TxStatus.FAILED); |
465 | } | |
466 | response.add(stakeWalletActivity); | |
467 | }); | |
468 | ||
469 |
1
1. getContentWalletActivityResponse : replaced return value with Collections.emptyList for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getContentWalletActivityResponse → KILLED |
return response; |
470 | } | |
471 | ||
472 | @Override | |
473 | public BaseFilterResponse<StakeRewardActivityResponse> getStakeRewardActivities( | |
474 | String stakeKey, Pageable pageable) { | |
475 | var stakeAddress = | |
476 | stakeAddressRepository | |
477 | .findByView(stakeKey) | |
478 |
1
1. lambda$getStakeRewardActivities$18 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeRewardActivities$18 → KILLED |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
479 | ||
480 |
1
1. getStakeRewardActivities : negated conditional → KILLED |
if (Boolean.FALSE.equals(fetchRewardDataService.useKoios())) { |
481 |
1
1. getStakeRewardActivities : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeRewardActivities → KILLED |
return new BaseFilterResponse<>(); |
482 | } | |
483 | ||
484 |
1
1. getStakeRewardActivities : negated conditional → KILLED |
if (!fetchRewardDataService.checkRewardAvailable(stakeKey)) { |
485 | boolean fetchRewardResponse = fetchRewardDataService.fetchReward(stakeKey); | |
486 |
1
1. getStakeRewardActivities : negated conditional → KILLED |
if (!fetchRewardResponse) { |
487 | throw new FetchRewardException(BusinessCode.FETCH_REWARD_ERROR); | |
488 | } | |
489 | } | |
490 | var withdrawList = withdrawalRepository.findEpochWithdrawalByStake(stakeAddress); | |
491 | List<StakeRewardActivityResponse> response = | |
492 | withdrawList.stream() | |
493 | .map( | |
494 | item -> | |
495 |
1
1. lambda$getStakeRewardActivities$19 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeRewardActivities$19 → KILLED |
StakeRewardActivityResponse.builder() |
496 | .epochNo(item.getEpoch()) | |
497 | .amount(item.getAmount()) | |
498 | .time(item.getTime()) | |
499 | .type(StakeRewardType.REWARD_WITHDRAWN) | |
500 | .build()) | |
501 | .collect(Collectors.toList()); | |
502 | var rewardList = rewardRepository.findRewardByStake(stakeAddress); | |
503 | response.addAll( | |
504 | rewardList.stream() | |
505 | .map( | |
506 | item -> | |
507 |
1
1. lambda$getStakeRewardActivities$20 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeRewardActivities$20 → KILLED |
StakeRewardActivityResponse.builder() |
508 | .epochNo(item.getEpoch()) | |
509 | .amount(item.getAmount()) | |
510 | .time(item.getTime()) | |
511 | .type(StakeRewardType.REWARD_RECEIVED) | |
512 | .build()) | |
513 | .collect(Collectors.toList())); | |
514 |
1
1. getStakeRewardActivities : negated conditional → KILLED |
if (pageable.getSort().equals(Sort.by(Sort.Direction.ASC, "time"))) { |
515 |
1
1. getStakeRewardActivities : removed call to java/util/List::sort → NO_COVERAGE |
response.sort(Comparator.comparing(StakeRewardActivityResponse::getEpochNo)); |
516 | } else { | |
517 |
1
1. getStakeRewardActivities : removed call to java/util/List::sort → SURVIVED |
response.sort(Comparator.comparing(StakeRewardActivityResponse::getEpochNo).reversed()); |
518 | } | |
519 | final int start = (int) pageable.getOffset(); | |
520 |
1
1. getStakeRewardActivities : Replaced integer addition with subtraction → KILLED |
final int end = Math.min((start + pageable.getPageSize()), response.size()); |
521 | Page<StakeRewardActivityResponse> page = | |
522 | new PageImpl<>(response.subList(start, end), pageable, response.size()); | |
523 |
1
1. getStakeRewardActivities : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeRewardActivities → KILLED |
return new BaseFilterResponse<>(page); |
524 | } | |
525 | ||
526 | @Override | |
527 | public BaseFilterResponse<StakeWalletActivityResponse> getStakeWalletActivitiesByDateRange( | |
528 | String stakeKey, StakeLifeCycleFilterRequest condition, Pageable pageable) { | |
529 | StakeAddress stakeAddress = | |
530 | stakeAddressRepository | |
531 | .findByView(stakeKey) | |
532 |
1
1. lambda$getStakeWalletActivitiesByDateRange$21 : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::lambda$getStakeWalletActivitiesByDateRange$21 → NO_COVERAGE |
.orElseThrow(() -> new NoContentException(BusinessCode.STAKE_ADDRESS_NOT_FOUND)); |
533 | LocalDateTime fromDate = cardanoConverters.genesisConfig().getStartTime(); | |
534 | LocalDateTime toDate = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC); | |
535 |
1
1. getStakeWalletActivitiesByDateRange : negated conditional → SURVIVED |
if (Objects.nonNull(condition.getFromDate())) { |
536 | fromDate = LocalDateTime.ofInstant(condition.getFromDate().toInstant(), ZoneOffset.UTC); | |
537 | } | |
538 |
1
1. getStakeWalletActivitiesByDateRange : negated conditional → SURVIVED |
if (Objects.nonNull(condition.getToDate())) { |
539 | toDate = LocalDateTime.ofInstant(condition.getToDate().toInstant(), ZoneOffset.UTC); | |
540 | } | |
541 | var txAmountList = | |
542 | addressTxAmountRepository.findTxAndAmountByStakeAndDateRange( | |
543 | stakeAddress.getView(), | |
544 | cardanoConverters.time().toSlot(fromDate), | |
545 | cardanoConverters.time().toSlot(toDate), | |
546 | pageable); | |
547 | ||
548 |
1
1. getStakeWalletActivitiesByDateRange : replaced return value with null for org/cardanofoundation/explorer/api/service/impl/StakeKeyLifeCycleServiceImpl::getStakeWalletActivitiesByDateRange → KILLED |
return new BaseFilterResponse<>(txAmountList, getContentWalletActivityResponse(txAmountList)); |
549 | } | |
550 | } | |
Mutations | ||
79 |
1.1 |
|
80 |
1.1 |
|
82 |
1.1 |
|
90 |
1.1 |
|
103 |
1.1 |
|
120 |
1.1 |
|
125 |
1.1 |
|
128 |
1.1 |
|
131 |
1.1 2.2 |
|
132 |
1.1 |
|
145 |
1.1 |
|
151 |
1.1 |
|
159 |
1.1 |
|
168 |
1.1 2.2 |
|
169 |
1.1 |
|
184 |
1.1 |
|
189 |
1.1 |
|
192 |
1.1 |
|
195 |
1.1 2.2 |
|
196 |
1.1 |
|
201 |
1.1 |
|
204 |
1.1 |
|
219 |
1.1 |
|
223 |
1.1 |
|
230 |
1.1 |
|
249 |
1.1 |
|
250 |
1.1 |
|
251 |
1.1 |
|
254 |
1.1 |
|
256 |
1.1 |
|
264 |
1.1 |
|
267 |
1.1 |
|
272 |
1.1 |
|
281 |
1.1 |
|
282 |
1.1 |
|
283 |
1.1 |
|
289 |
1.1 |
|
292 |
1.1 |
|
295 |
1.1 2.2 |
|
296 |
1.1 |
|
301 |
1.1 |
|
304 |
1.1 |
|
317 |
1.1 |
|
318 |
1.1 |
|
320 |
1.1 |
|
327 |
1.1 |
|
336 |
1.1 |
|
347 |
1.1 |
|
363 |
1.1 |
|
368 |
1.1 |
|
371 |
1.1 |
|
374 |
1.1 2.2 |
|
375 |
1.1 |
|
388 |
1.1 |
|
398 |
1.1 |
|
407 |
1.1 |
|
417 |
1.1 2.2 |
|
418 |
1.1 |
|
433 |
1.1 |
|
437 |
1.1 |
|
454 |
1.1 |
|
457 |
1.1 |
|
458 |
1.1 |
|
459 |
1.1 |
|
461 |
1.1 |
|
462 |
1.1 |
|
464 |
1.1 |
|
469 |
1.1 |
|
478 |
1.1 |
|
480 |
1.1 |
|
481 |
1.1 |
|
484 |
1.1 |
|
486 |
1.1 |
|
495 |
1.1 |
|
507 |
1.1 |
|
514 |
1.1 |
|
515 |
1.1 |
|
517 |
1.1 |
|
520 |
1.1 |
|
523 |
1.1 |
|
532 |
1.1 |
|
535 |
1.1 |
|
538 |
1.1 |
|
548 |
1.1 |