TransferCryptoRequest.java
package com.distasilucas.cryptobalancetracker.model.request.usercrypto;
import com.distasilucas.cryptobalancetracker.model.response.usercrypto.FromPlatform;
import com.distasilucas.cryptobalancetracker.model.response.usercrypto.ToPlatform;
import com.distasilucas.cryptobalancetracker.model.response.usercrypto.TransferCryptoResponse;
import jakarta.validation.constraints.DecimalMax;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
import org.hibernate.validator.constraints.UUID;
import java.math.BigDecimal;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.NETWORK_FEE_DIGITS;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.NETWORK_FEE_MIN;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.NETWORK_FEE_NOT_NULL;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.QUANTITY_TO_TRANSFER_DECIMAL_MAX;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.QUANTITY_TO_TRANSFER_DIGITS;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.QUANTITY_TO_TRANSFER_NOT_NULL;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.QUANTITY_TO_TRANSFER_POSITIVE;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.TO_PLATFORM_ID_NOT_BLANK;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.TO_PLATFORM_ID_UUID;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.USER_CRYPTO_ID_NOT_BLANK;
import static com.distasilucas.cryptobalancetracker.constants.ValidationConstants.USER_CRYPTO_ID_UUID;
public record TransferCryptoRequest(
@NotBlank(message = USER_CRYPTO_ID_NOT_BLANK)
@UUID(message = USER_CRYPTO_ID_UUID)
String userCryptoId,
@NotNull(message = QUANTITY_TO_TRANSFER_NOT_NULL)
@Digits(integer = 16, fraction = 12, message = QUANTITY_TO_TRANSFER_DIGITS)
@DecimalMax(value = "9999999999999999.999999999999", message = QUANTITY_TO_TRANSFER_DECIMAL_MAX)
@Positive(message = QUANTITY_TO_TRANSFER_POSITIVE)
BigDecimal quantityToTransfer,
@NotNull(message = NETWORK_FEE_NOT_NULL)
@Digits(integer = 16, fraction = 12, message = NETWORK_FEE_DIGITS)
@Min(value = 0, message = NETWORK_FEE_MIN)
BigDecimal networkFee,
Boolean sendFullQuantity,
@NotBlank(message = TO_PLATFORM_ID_NOT_BLANK)
@UUID(message = TO_PLATFORM_ID_UUID)
String toPlatformId
) {
public TransferCryptoResponse toTransferCryptoResponse(
BigDecimal remainingCryptoQuantity,
BigDecimal newQuantity,
BigDecimal quantityToSendReceive
) {
var fromPlatform = new FromPlatform(
userCryptoId,
networkFee.toPlainString(),
quantityToTransfer.toPlainString(),
calculateTotalToSubtract(remainingCryptoQuantity).toPlainString(),
quantityToSendReceive.toPlainString(),
remainingCryptoQuantity.toPlainString(),
sendFullQuantity
);
var toPlatform = new ToPlatform(toPlatformId, newQuantity.toPlainString());
return new TransferCryptoResponse(fromPlatform, toPlatform);
}
public BigDecimal calculateTotalToSubtract(BigDecimal remainingCryptoQuantity) {
if (Boolean.TRUE.equals(sendFullQuantity)) {
return remainingCryptoQuantity.compareTo(BigDecimal.ZERO) > 0 ?
networkFee.add(quantityToTransfer) : quantityToTransfer;
} else {
return quantityToTransfer;
}
}
public BigDecimal calculateQuantityToSendReceive(BigDecimal remainingCryptoQuantity, BigDecimal availableQuantity) {
BigDecimal quantityToSendReceive;
if (Boolean.TRUE.equals(sendFullQuantity)) {
quantityToSendReceive = remainingCryptoQuantity.equals(BigDecimal.ZERO) ? availableQuantity.subtract(networkFee) : quantityToTransfer;
} else {
quantityToSendReceive = quantityToTransfer.subtract(networkFee);
}
return quantityToSendReceive.stripTrailingZeros();
}
public BigDecimal calculateRemainingCryptoQuantity(BigDecimal availableQuantity) {
BigDecimal remaining;
if (Boolean.TRUE.equals(sendFullQuantity)) {
remaining = availableQuantity.subtract(quantityToTransfer.add(networkFee));
} else {
remaining = availableQuantity.subtract(quantityToTransfer);
}
return remaining.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : remaining.stripTrailingZeros();
}
public boolean hasInsufficientBalance(BigDecimal availableQuantity) {
return availableQuantity.compareTo(quantityToTransfer) < 0 || networkFee.compareTo(availableQuantity) > 0;
}
}