package com.xfestudio.xfeservermanager.core.economy;
import java.time.Instant;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
/** Immutable ledger entry produced by one committed economy mutation. */
public record EconomyTransaction(
UUID id,
UUID currencyId,
String currencyCode,
String kind,
UUID sourcePlayerId,
String sourcePlayerName,
UUID targetPlayerId,
String targetPlayerName,
String amount,
String sourceBalanceBefore,
String sourceBalanceAfter,
String targetBalanceBefore,
String targetBalanceAfter,
String reason,
String actor,
String origin,
String correlationId,
Instant createdAt) {
public static final Set<String> KINDS = Set.of("initial", "deposit", "withdraw", "set", "transfer");
public EconomyTransaction {
Objects.requireNonNull(id, "id");
Objects.requireNonNull(currencyId, "currencyId");
currencyCode = required(currencyCode, "currencyCode", 32);
kind = Objects.toString(kind, "").strip().toLowerCase(Locale.ROOT);
if (!KINDS.contains(kind)) throw new IllegalArgumentException("unsupported economy transaction kind");
sourcePlayerName = optional(sourcePlayerName, 64);
targetPlayerName = optional(targetPlayerName, 64);
amount = required(amount, "amount", 64);
sourceBalanceBefore = optional(sourceBalanceBefore, 64);
sourceBalanceAfter = optional(sourceBalanceAfter, 64);
targetBalanceBefore = optional(targetBalanceBefore, 64);
targetBalanceAfter = optional(targetBalanceAfter, 64);
reason = required(reason, "reason", 256);
actor = required(actor, "actor", 128);
origin = required(origin, "origin", 32);
correlationId = optional(correlationId, 128);
Objects.requireNonNull(createdAt, "createdAt");
}
private static String required(String value, String field, int maximum) {
String result = optional(value, maximum);
if (result.isEmpty()) throw new IllegalArgumentException(field + " must not be blank");
return result;
}
private static String optional(String value, int maximum) {
String result = Objects.toString(value, "").strip();
if (result.length() > maximum || result.codePoints().anyMatch(Character::isISOControl)) {
throw new IllegalArgumentException("economy transaction text is invalid");
}
return result;
}
}
package com.xfestudio.xfeservermanager.core.economy;
import java.time.Instant;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
/** Immutable ledger entry produced by one committed economy mutation. */
public record EconomyTransaction(
UUID id,
UUID currencyId,
String currencyCode,
String kind,
UUID sourcePlayerId,
String sourcePlayerName,
UUID targetPlayerId,
String targetPlayerName,
String amount,
String sourceBalanceBefore,
String sourceBalanceAfter,
String targetBalanceBefore,
String targetBalanceAfter,
String reason,
String actor,
String origin,
String correlationId,
Instant createdAt) {
public static final Set<String> KINDS = Set.of("initial", "deposit", "withdraw", "set", "transfer");
public EconomyTransaction {
Objects.requireNonNull(id, "id");
Objects.requireNonNull(currencyId, "currencyId");
currencyCode = required(currencyCode, "currencyCode", 32);
kind = Objects.toString(kind, "").strip().toLowerCase(Locale.ROOT);
if (!KINDS.contains(kind)) throw new IllegalArgumentException("unsupported economy transaction kind");
sourcePlayerName = optional(sourcePlayerName, 64);
targetPlayerName = optional(targetPlayerName, 64);
amount = required(amount, "amount", 64);
sourceBalanceBefore = optional(sourceBalanceBefore, 64);
sourceBalanceAfter = optional(sourceBalanceAfter, 64);
targetBalanceBefore = optional(targetBalanceBefore, 64);
targetBalanceAfter = optional(targetBalanceAfter, 64);
reason = required(reason, "reason", 256);
actor = required(actor, "actor", 128);
origin = required(origin, "origin", 32);
correlationId = optional(correlationId, 128);
Objects.requireNonNull(createdAt, "createdAt");
}
private static String required(String value, String field, int maximum) {
String result = optional(value, maximum);
if (result.isEmpty()) throw new IllegalArgumentException(field + " must not be blank");
return result;
}
private static String optional(String value, int maximum) {
String result = Objects.toString(value, "").strip();
if (result.length() > maximum || result.codePoints().anyMatch(Character::isISOControl)) {
throw new IllegalArgumentException("economy transaction text is invalid");
}
return result;
}
}