Deprecate old CLI console output formatters

A minor refactoring of some deprecated classes is included.
This commit is contained in:
ghubstan 2021-11-07 13:51:27 -03:00
parent 19436c3e2f
commit 08d16e6040
No known key found for this signature in database
GPG key ID: E35592D6800A861E
8 changed files with 353 additions and 244 deletions

View file

@ -20,6 +20,7 @@ package bisq.cli;
import static com.google.common.base.Strings.padEnd;
import static com.google.common.base.Strings.padStart;
@Deprecated
class ColumnHeaderConstants {
// For inserting 2 spaces between column headers.

View file

@ -20,15 +20,16 @@ package bisq.cli;
import java.util.ArrayList;
import java.util.List;
class CryptoCurrencyUtil {
public class CryptoCurrencyUtil {
public static boolean isSupportedCryptoCurrency(String currencyCode) {
public static boolean apiDoesSupportCryptoCurrency(String currencyCode) {
return getSupportedCryptoCurrencies().contains(currencyCode.toUpperCase());
}
public static List<String> getSupportedCryptoCurrencies() {
final List<String> result = new ArrayList<>();
result.add("BSQ");
// result.add("XMR"); // TODO Uncomment when XMR support is added.
result.sort(String::compareTo);
return result;
}

View file

@ -39,14 +39,15 @@ public class CurrencyFormat {
// Use the US locale for all DecimalFormat objects.
private static final DecimalFormatSymbols DECIMAL_FORMAT_SYMBOLS = DecimalFormatSymbols.getInstance(Locale.US);
// Formats numbers in US locale, human friendly style.
// Format numbers in US locale for CLI console.
private static final NumberFormat FRIENDLY_NUMBER_FORMAT = NumberFormat.getInstance(Locale.US);
// Formats numbers for internal use, i.e., grpc request parameters.
private static final DecimalFormat INTERNAL_FIAT_DECIMAL_FORMAT = new DecimalFormat("##############0.0000");
static final BigDecimal SATOSHI_DIVISOR = new BigDecimal(100_000_000);
static final DecimalFormat BTC_FORMAT = new DecimalFormat("###,##0.00000000", DECIMAL_FORMAT_SYMBOLS);
static final DecimalFormat SATOSHI_FORMAT = new DecimalFormat("###,##0.00000000", DECIMAL_FORMAT_SYMBOLS);
static final DecimalFormat BTC_FORMAT = new DecimalFormat("###,##0.########", DECIMAL_FORMAT_SYMBOLS);
static final DecimalFormat BTC_TX_FEE_FORMAT = new DecimalFormat("###,###,##0", DECIMAL_FORMAT_SYMBOLS);
static final BigDecimal BSQ_SATOSHI_DIVISOR = new BigDecimal(100);
@ -57,6 +58,11 @@ public class CurrencyFormat {
@SuppressWarnings("BigDecimalMethodWithoutRoundingCalled")
public static String formatSatoshis(long sats) {
return SATOSHI_FORMAT.format(BigDecimal.valueOf(sats).divide(SATOSHI_DIVISOR));
}
@SuppressWarnings("BigDecimalMethodWithoutRoundingCalled")
public static String formatBtc(long sats) {
return BTC_FORMAT.format(BigDecimal.valueOf(sats).divide(SATOSHI_DIVISOR));
}
@ -84,22 +90,25 @@ public class CurrencyFormat {
formatFeeSatoshis(txFeeRateInfo.getMinFeeServiceRate()));
}
@Deprecated
public static String formatAmountRange(long minAmount, long amount) {
return minAmount != amount
? formatSatoshis(minAmount) + " - " + formatSatoshis(amount)
: formatSatoshis(amount);
}
@Deprecated
public static String formatVolumeRange(long minVolume, long volume) {
return minVolume != volume
? formatOfferVolume(minVolume) + " - " + formatOfferVolume(volume)
: formatOfferVolume(volume);
? formatFiatVolume(minVolume) + " - " + formatFiatVolume(volume)
: formatFiatVolume(volume);
}
@Deprecated
public static String formatCryptoCurrencyVolumeRange(long minVolume, long volume) {
return minVolume != volume
? formatCryptoCurrencyOfferVolume(minVolume) + " - " + formatCryptoCurrencyOfferVolume(volume)
: formatCryptoCurrencyOfferVolume(volume);
? formatCryptoCurrencyVolume(minVolume) + " - " + formatCryptoCurrencyVolume(volume)
: formatCryptoCurrencyVolume(volume);
}
public static String formatInternalFiatPrice(BigDecimal price) {
@ -128,22 +137,31 @@ public class CurrencyFormat {
return FRIENDLY_NUMBER_FORMAT.format((double) price / SATOSHI_DIVISOR.doubleValue());
}
public static String formatOfferVolume(long volume) {
public static String formatFiatVolume(long volume) {
FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(0);
FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(0);
FRIENDLY_NUMBER_FORMAT.setRoundingMode(HALF_UP);
return FRIENDLY_NUMBER_FORMAT.format((double) volume / 10_000);
}
public static String formatCryptoCurrencyOfferVolume(long volume) {
FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(2);
FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(2);
public static String formatCryptoCurrencyVolume(long volume) {
int defaultPrecision = 2;
return formatCryptoCurrencyVolume(volume, defaultPrecision);
}
public static String formatCryptoCurrencyVolume(long volume, int precision) {
FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(precision);
FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(precision);
FRIENDLY_NUMBER_FORMAT.setRoundingMode(HALF_UP);
return FRIENDLY_NUMBER_FORMAT.format((double) volume / SATOSHI_DIVISOR.doubleValue());
}
public static long toInternalFiatPrice(BigDecimal humanFriendlyFiatPrice) {
return humanFriendlyFiatPrice.multiply(new BigDecimal(10_000)).longValue();
public static long toInternalFiatPrice(BigDecimal fiatPrice) {
return fiatPrice.multiply(new BigDecimal(10_000)).longValue();
}
public static long toInternalCryptoCurrencyPrice(BigDecimal altcoinPrice) {
return altcoinPrice.multiply(new BigDecimal(100_000_000)).longValue();
}
public static long toSatoshis(String btc) {

View file

@ -27,6 +27,7 @@ import static java.lang.String.format;
import static protobuf.OfferDirection.BUY;
import static protobuf.OfferDirection.SELL;
@Deprecated
class DirectionFormat {
static int getLongestDirectionColWidth(List<OfferInfo> offers) {

View file

@ -0,0 +1,309 @@
package bisq.cli;
import bisq.proto.grpc.OfferInfo;
import com.google.common.annotations.VisibleForTesting;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import static bisq.cli.ColumnHeaderConstants.*;
import static bisq.cli.CurrencyFormat.*;
import static bisq.cli.DirectionFormat.directionFormat;
import static bisq.cli.DirectionFormat.getLongestDirectionColWidth;
import static bisq.cli.TableFormat.formatTimestamp;
import static bisq.cli.TableFormat.getLongestColumnSize;
import static com.google.common.base.Strings.padEnd;
import static com.google.common.base.Strings.padStart;
import static java.lang.String.format;
@Deprecated
@VisibleForTesting
public class OfferFormat {
public static String formatOfferTable(List<OfferInfo> offers, String currencyCode) {
if (offers == null || offers.isEmpty())
throw new IllegalArgumentException(format("%s offer list is empty", currencyCode.toLowerCase()));
String baseCurrencyCode = offers.get(0).getBaseCurrencyCode();
boolean isMyOffer = offers.get(0).getIsMyOffer();
return baseCurrencyCode.equalsIgnoreCase("BTC")
? formatFiatOfferTable(offers, currencyCode, isMyOffer)
: formatCryptoCurrencyOfferTable(offers, baseCurrencyCode, isMyOffer);
}
private static String formatFiatOfferTable(List<OfferInfo> offers,
String fiatCurrencyCode,
boolean isMyOffer) {
// Some column values might be longer than header, so we need to calculate them.
int amountColWith = getLongestAmountColWidth(offers);
int volumeColWidth = getLongestVolumeColWidth(offers);
int paymentMethodColWidth = getLongestPaymentMethodColWidth(offers);
// "Enabled" and "Trigger Price" columns are displayed for my offers only.
String enabledHeaderFormat = isMyOffer ?
COL_HEADER_ENABLED + COL_HEADER_DELIMITER
: "";
String triggerPriceHeaderFormat = isMyOffer ?
// COL_HEADER_TRIGGER_PRICE includes %s -> fiatCurrencyCode
COL_HEADER_TRIGGER_PRICE + COL_HEADER_DELIMITER
: "";
String headersFormat = enabledHeaderFormat
+ COL_HEADER_DIRECTION + COL_HEADER_DELIMITER
// COL_HEADER_PRICE includes %s -> fiatCurrencyCode
+ COL_HEADER_PRICE + COL_HEADER_DELIMITER
+ padStart(COL_HEADER_AMOUNT, amountColWith, ' ') + COL_HEADER_DELIMITER
// COL_HEADER_VOLUME includes %s -> fiatCurrencyCode
+ padStart(COL_HEADER_VOLUME, volumeColWidth, ' ') + COL_HEADER_DELIMITER
+ triggerPriceHeaderFormat
+ padEnd(COL_HEADER_PAYMENT_METHOD, paymentMethodColWidth, ' ') + COL_HEADER_DELIMITER
+ COL_HEADER_CREATION_DATE + COL_HEADER_DELIMITER
+ COL_HEADER_UUID.trim() + "%n";
String headerLine = format(headersFormat,
fiatCurrencyCode.toUpperCase(),
fiatCurrencyCode.toUpperCase(),
// COL_HEADER_TRIGGER_PRICE includes %s -> fiatCurrencyCode
isMyOffer ? fiatCurrencyCode.toUpperCase() : "");
String colDataFormat = getFiatOfferColDataFormat(isMyOffer,
amountColWith,
volumeColWidth,
paymentMethodColWidth);
return formattedFiatOfferTable(offers, isMyOffer, headerLine, colDataFormat);
}
private static String formattedFiatOfferTable(List<OfferInfo> offers,
boolean isMyOffer,
String headerLine,
String colDataFormat) {
if (isMyOffer) {
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
formatEnabled(o),
o.getDirection(),
formatPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatVolumeRange(o.getMinVolume(), o.getVolume()),
o.getTriggerPrice() == 0 ? "" : formatPrice(o.getTriggerPrice()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
} else {
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
o.getDirection(),
formatPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatVolumeRange(o.getMinVolume(), o.getVolume()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
}
}
private static String getFiatOfferColDataFormat(boolean isMyOffer,
int amountColWith,
int volumeColWidth,
int paymentMethodColWidth) {
if (isMyOffer) {
return "%-" + (COL_HEADER_ENABLED.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%-" + (COL_HEADER_DIRECTION.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%" + (COL_HEADER_PRICE.length() - 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %" + (COL_HEADER_TRIGGER_PRICE.length() - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
} else {
return "%-" + (COL_HEADER_DIRECTION.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%" + (COL_HEADER_PRICE.length() - 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
}
}
private static String formatCryptoCurrencyOfferTable(List<OfferInfo> offers,
String cryptoCurrencyCode,
boolean isMyOffer) {
// Some column values might be longer than header, so we need to calculate them.
int directionColWidth = getLongestDirectionColWidth(offers);
int amountColWith = getLongestAmountColWidth(offers);
int volumeColWidth = getLongestCryptoCurrencyVolumeColWidth(offers);
int paymentMethodColWidth = getLongestPaymentMethodColWidth(offers);
// "Enabled" column is displayed for my offers only.
String enabledHeaderFormat = isMyOffer ?
COL_HEADER_ENABLED + COL_HEADER_DELIMITER
: "";
Supplier<Boolean> shouldShowTriggerPrice = () -> isMyOffer && !cryptoCurrencyCode.equalsIgnoreCase("BSQ");
String triggerPriceHeaderFormat = shouldShowTriggerPrice.get()
? COL_HEADER_TRIGGER_PRICE + COL_HEADER_DELIMITER
: "";
// TODO use memoize function to avoid duplicate the formatting done above?
String headersFormat = enabledHeaderFormat
+ padEnd(COL_HEADER_DIRECTION, directionColWidth, ' ') + COL_HEADER_DELIMITER
+ COL_HEADER_PRICE_OF_ALTCOIN + COL_HEADER_DELIMITER // includes %s -> cryptoCurrencyCode
+ padStart(COL_HEADER_AMOUNT, amountColWith, ' ') + COL_HEADER_DELIMITER
// COL_HEADER_VOLUME includes %s -> cryptoCurrencyCode
+ padStart(COL_HEADER_VOLUME, volumeColWidth, ' ') + COL_HEADER_DELIMITER
+ triggerPriceHeaderFormat // COL_HEADER_TRIGGER_PRICE includes %s -> cryptoCurrencyCode
+ padEnd(COL_HEADER_PAYMENT_METHOD, paymentMethodColWidth, ' ') + COL_HEADER_DELIMITER
+ COL_HEADER_CREATION_DATE + COL_HEADER_DELIMITER
+ COL_HEADER_UUID.trim() + "%n";
String headerLine = format(headersFormat,
cryptoCurrencyCode.toUpperCase(),
cryptoCurrencyCode.toUpperCase(),
shouldShowTriggerPrice.get() ? cryptoCurrencyCode.toUpperCase() : "");
String colDataFormat = getCryptoCurrencyOfferColDataFormat(isMyOffer,
shouldShowTriggerPrice.get(),
directionColWidth,
amountColWith,
volumeColWidth,
paymentMethodColWidth);
if (isMyOffer) {
if (shouldShowTriggerPrice.get()) {
// Is my non-BSQ altcoin offer. Show ENABLED and TRIGGER_PRICE data.
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
formatEnabled(o),
directionFormat.apply(o),
formatCryptoCurrencyPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatCryptoCurrencyVolumeRange(o.getMinVolume(), o.getVolume()),
o.getTriggerPrice() == 0 ? "" : formatCryptoCurrencyPrice(o.getTriggerPrice()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
} else {
// Is my BSQ altcoin offer. Show ENABLED, but not TRIGGER_PRICE data.
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
formatEnabled(o),
directionFormat.apply(o),
formatCryptoCurrencyPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatCryptoCurrencyVolumeRange(o.getMinVolume(), o.getVolume()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
}
} else {
// Not my offer. Do not show ENABLED and TRIGGER_PRICE cols.
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
directionFormat.apply(o),
formatCryptoCurrencyPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatCryptoCurrencyVolumeRange(o.getMinVolume(), o.getVolume()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
}
}
private static String getCryptoCurrencyOfferColDataFormat(boolean isMyOffer,
boolean shouldShowTriggerPrice,
int directionColWidth,
int amountColWith,
int volumeColWidth,
int paymentMethodColWidth) {
if (isMyOffer) {
return getMyCryptoOfferColDataFormat(shouldShowTriggerPrice,
directionColWidth,
amountColWith,
volumeColWidth,
paymentMethodColWidth);
} else {
// Not my offer. Do not show ENABLED and TRIGGER_PRICE cols.
return "%-" + directionColWidth + "s"
+ "%" + (COL_HEADER_PRICE_OF_ALTCOIN.length() + 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
}
}
private static String getMyCryptoOfferColDataFormat(boolean shouldShowTriggerPrice,
int directionColWidth,
int amountColWith,
int volumeColWidth,
int paymentMethodColWidth) {
if (shouldShowTriggerPrice) {
// Is my non-BSQ altcoin offer. Show ENABLED and TRIGGER_PRICE cols.
return "%-" + (COL_HEADER_ENABLED.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%-" + directionColWidth + "s"
+ "%" + (COL_HEADER_PRICE_OF_ALTCOIN.length() + 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %" + (COL_HEADER_TRIGGER_PRICE.length() - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
} else {
// Is my BSQ altcoin offer. Show ENABLED, but not TRIGGER_PRICE col.
return "%-" + (COL_HEADER_ENABLED.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%-" + directionColWidth + "s"
+ "%" + (COL_HEADER_PRICE_OF_ALTCOIN.length() + 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
}
}
private static String formatEnabled(OfferInfo offerInfo) {
if (offerInfo.getIsMyOffer() && offerInfo.getIsMyPendingOffer())
return "PENDING";
else
return offerInfo.getIsActivated() ? "YES" : "NO";
}
private static int getLongestPaymentMethodColWidth(List<OfferInfo> offers) {
return getLongestColumnSize(
COL_HEADER_PAYMENT_METHOD.length(),
offers.stream()
.map(OfferInfo::getPaymentMethodShortName)
.collect(Collectors.toList()));
}
private static int getLongestAmountColWidth(List<OfferInfo> offers) {
return getLongestColumnSize(
COL_HEADER_AMOUNT.length(),
offers.stream()
.map(o -> formatAmountRange(o.getMinAmount(), o.getAmount()))
.collect(Collectors.toList()));
}
private static int getLongestVolumeColWidth(List<OfferInfo> offers) {
// Pad this col width by 1 space.
return 1 + getLongestColumnSize(
COL_HEADER_VOLUME.length(),
offers.stream()
.map(o -> formatVolumeRange(o.getMinVolume(), o.getVolume()))
.collect(Collectors.toList()));
}
private static int getLongestCryptoCurrencyVolumeColWidth(List<OfferInfo> offers) {
// Pad this col width by 1 space.
return 1 + getLongestColumnSize(
COL_HEADER_VOLUME.length(),
offers.stream()
.map(o -> formatCryptoCurrencyVolumeRange(o.getMinVolume(), o.getVolume()))
.collect(Collectors.toList()));
}
}

View file

@ -21,7 +21,6 @@ import bisq.proto.grpc.AddressBalanceInfo;
import bisq.proto.grpc.BalancesInfo;
import bisq.proto.grpc.BsqBalanceInfo;
import bisq.proto.grpc.BtcBalanceInfo;
import bisq.proto.grpc.OfferInfo;
import protobuf.PaymentAccount;
@ -35,16 +34,15 @@ import java.util.TimeZone;
import java.util.stream.Collectors;
import static bisq.cli.ColumnHeaderConstants.*;
import static bisq.cli.CurrencyFormat.*;
import static bisq.cli.DirectionFormat.directionFormat;
import static bisq.cli.DirectionFormat.getLongestDirectionColWidth;
import static bisq.cli.CurrencyFormat.formatBsq;
import static bisq.cli.CurrencyFormat.formatSatoshis;
import static com.google.common.base.Strings.padEnd;
import static com.google.common.base.Strings.padStart;
import static java.lang.String.format;
import static java.util.Collections.max;
import static java.util.Comparator.comparing;
import static java.util.TimeZone.getTimeZone;
@Deprecated
@VisibleForTesting
public class TableFormat {
@ -145,234 +143,13 @@ public class TableFormat {
.collect(Collectors.joining("\n"));
}
public static String formatOfferTable(List<OfferInfo> offers, String currencyCode) {
if (offers == null || offers.isEmpty())
throw new IllegalArgumentException(format("%s offer list is empty", currencyCode.toLowerCase()));
String baseCurrencyCode = offers.get(0).getBaseCurrencyCode();
boolean isMyOffer = offers.get(0).getIsMyOffer();
return baseCurrencyCode.equalsIgnoreCase("BTC")
? formatFiatOfferTable(offers, currencyCode, isMyOffer)
: formatCryptoCurrencyOfferTable(offers, baseCurrencyCode, isMyOffer);
}
private static String formatFiatOfferTable(List<OfferInfo> offers,
String fiatCurrencyCode,
boolean isMyOffer) {
// Some column values might be longer than header, so we need to calculate them.
int amountColWith = getLongestAmountColWidth(offers);
int volumeColWidth = getLongestVolumeColWidth(offers);
int paymentMethodColWidth = getLongestPaymentMethodColWidth(offers);
// "Enabled" and "Trigger Price" columns are displayed for my offers only.
String enabledHeaderFormat = isMyOffer ?
COL_HEADER_ENABLED + COL_HEADER_DELIMITER
: "";
String triggerPriceHeaderFormat = isMyOffer ?
// COL_HEADER_TRIGGER_PRICE includes %s -> fiatCurrencyCode
COL_HEADER_TRIGGER_PRICE + COL_HEADER_DELIMITER
: "";
String headersFormat = enabledHeaderFormat
+ COL_HEADER_DIRECTION + COL_HEADER_DELIMITER
// COL_HEADER_PRICE includes %s -> fiatCurrencyCode
+ COL_HEADER_PRICE + COL_HEADER_DELIMITER
+ padStart(COL_HEADER_AMOUNT, amountColWith, ' ') + COL_HEADER_DELIMITER
// COL_HEADER_VOLUME includes %s -> fiatCurrencyCode
+ padStart(COL_HEADER_VOLUME, volumeColWidth, ' ') + COL_HEADER_DELIMITER
+ triggerPriceHeaderFormat
+ padEnd(COL_HEADER_PAYMENT_METHOD, paymentMethodColWidth, ' ') + COL_HEADER_DELIMITER
+ COL_HEADER_CREATION_DATE + COL_HEADER_DELIMITER
+ COL_HEADER_UUID.trim() + "%n";
String headerLine = format(headersFormat,
fiatCurrencyCode.toUpperCase(),
fiatCurrencyCode.toUpperCase(),
// COL_HEADER_TRIGGER_PRICE includes %s -> fiatCurrencyCode
isMyOffer ? fiatCurrencyCode.toUpperCase() : "");
String colDataFormat = getFiatOfferColDataFormat(isMyOffer,
amountColWith,
volumeColWidth,
paymentMethodColWidth);
return formattedFiatOfferTable(offers, isMyOffer, headerLine, colDataFormat);
}
private static String formattedFiatOfferTable(List<OfferInfo> offers,
boolean isMyOffer,
String headerLine,
String colDataFormat) {
if (isMyOffer) {
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
formatEnabled(o),
o.getDirection(),
formatPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatVolumeRange(o.getMinVolume(), o.getVolume()),
o.getTriggerPrice() == 0 ? "" : formatPrice(o.getTriggerPrice()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
} else {
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
o.getDirection(),
formatPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatVolumeRange(o.getMinVolume(), o.getVolume()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
}
}
private static String getFiatOfferColDataFormat(boolean isMyOffer,
int amountColWith,
int volumeColWidth,
int paymentMethodColWidth) {
if (isMyOffer) {
return "%-" + (COL_HEADER_ENABLED.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%-" + (COL_HEADER_DIRECTION.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%" + (COL_HEADER_PRICE.length() - 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %" + (COL_HEADER_TRIGGER_PRICE.length() - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
} else {
return "%-" + (COL_HEADER_DIRECTION.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%" + (COL_HEADER_PRICE.length() - 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
}
}
private static String formatCryptoCurrencyOfferTable(List<OfferInfo> offers,
String cryptoCurrencyCode,
boolean isMyOffer) {
// Some column values might be longer than header, so we need to calculate them.
int directionColWidth = getLongestDirectionColWidth(offers);
int amountColWith = getLongestAmountColWidth(offers);
int volumeColWidth = getLongestCryptoCurrencyVolumeColWidth(offers);
int paymentMethodColWidth = getLongestPaymentMethodColWidth(offers);
// "Enabled" column is displayed for my offers only.
String enabledHeaderFormat = isMyOffer ?
COL_HEADER_ENABLED + COL_HEADER_DELIMITER
: "";
// TODO use memoize function to avoid duplicate the formatting done above?
String headersFormat = enabledHeaderFormat
+ padEnd(COL_HEADER_DIRECTION, directionColWidth, ' ') + COL_HEADER_DELIMITER
+ COL_HEADER_PRICE_OF_ALTCOIN + COL_HEADER_DELIMITER // includes %s -> cryptoCurrencyCode
+ padStart(COL_HEADER_AMOUNT, amountColWith, ' ') + COL_HEADER_DELIMITER
// COL_HEADER_VOLUME includes %s -> cryptoCurrencyCode
+ padStart(COL_HEADER_VOLUME, volumeColWidth, ' ') + COL_HEADER_DELIMITER
+ padEnd(COL_HEADER_PAYMENT_METHOD, paymentMethodColWidth, ' ') + COL_HEADER_DELIMITER
+ COL_HEADER_CREATION_DATE + COL_HEADER_DELIMITER
+ COL_HEADER_UUID.trim() + "%n";
String headerLine = format(headersFormat,
cryptoCurrencyCode.toUpperCase(),
cryptoCurrencyCode.toUpperCase());
String colDataFormat;
if (isMyOffer) {
colDataFormat = "%-" + (COL_HEADER_ENABLED.length() + COL_HEADER_DELIMITER.length()) + "s"
+ "%-" + directionColWidth + "s"
+ "%" + (COL_HEADER_PRICE_OF_ALTCOIN.length() + 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
} else {
colDataFormat = "%-" + directionColWidth + "s"
+ "%" + (COL_HEADER_PRICE_OF_ALTCOIN.length() + 1) + "s"
+ " %" + amountColWith + "s"
+ " %" + (volumeColWidth - 1) + "s"
+ " %-" + paymentMethodColWidth + "s"
+ " %-" + (COL_HEADER_CREATION_DATE.length()) + "s"
+ " %-" + COL_HEADER_UUID.length() + "s";
}
if (isMyOffer) {
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
formatEnabled(o),
directionFormat.apply(o),
formatCryptoCurrencyPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatCryptoCurrencyVolumeRange(o.getMinVolume(), o.getVolume()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
} else {
return headerLine
+ offers.stream()
.map(o -> format(colDataFormat,
directionFormat.apply(o),
formatCryptoCurrencyPrice(o.getPrice()),
formatAmountRange(o.getMinAmount(), o.getAmount()),
formatCryptoCurrencyVolumeRange(o.getMinVolume(), o.getVolume()),
o.getPaymentMethodShortName(),
formatTimestamp(o.getDate()),
o.getId()))
.collect(Collectors.joining("\n"));
}
}
private static String formatEnabled(OfferInfo offerInfo) {
if (offerInfo.getIsMyOffer() && offerInfo.getIsMyPendingOffer())
return "PENDING";
else
return offerInfo.getIsActivated() ? "YES" : "NO";
}
private static int getLongestPaymentMethodColWidth(List<OfferInfo> offers) {
return getLongestColumnSize(
COL_HEADER_PAYMENT_METHOD.length(),
offers.stream()
.map(OfferInfo::getPaymentMethodShortName)
.collect(Collectors.toList()));
}
private static int getLongestAmountColWidth(List<OfferInfo> offers) {
return getLongestColumnSize(
COL_HEADER_AMOUNT.length(),
offers.stream()
.map(o -> formatAmountRange(o.getMinAmount(), o.getAmount()))
.collect(Collectors.toList()));
}
private static int getLongestVolumeColWidth(List<OfferInfo> offers) {
// Pad this col width by 1 space.
return 1 + getLongestColumnSize(
COL_HEADER_VOLUME.length(),
offers.stream()
.map(o -> formatVolumeRange(o.getMinVolume(), o.getVolume()))
.collect(Collectors.toList()));
}
private static int getLongestCryptoCurrencyVolumeColWidth(List<OfferInfo> offers) {
// Pad this col width by 1 space.
return 1 + getLongestColumnSize(
COL_HEADER_VOLUME.length(),
offers.stream()
.map(o -> formatCryptoCurrencyVolumeRange(o.getMinVolume(), o.getVolume()))
.collect(Collectors.toList()));
}
// Return size of the longest string value, or the header.len, whichever is greater.
private static int getLongestColumnSize(int headerLength, List<String> strings) {
static int getLongestColumnSize(int headerLength, List<String> strings) {
int longest = max(strings, comparing(String::length)).length();
return Math.max(longest, headerLength);
}
private static String formatTimestamp(long timestamp) {
static String formatTimestamp(long timestamp) {
DATE_FORMAT_ISO_8601.setTimeZone(TZ_UTC);
return DATE_FORMAT_ISO_8601.format(new Date(timestamp));
}

View file

@ -30,6 +30,7 @@ import static bisq.cli.ColumnHeaderConstants.*;
import static bisq.cli.CurrencyFormat.*;
import static com.google.common.base.Strings.padEnd;
@Deprecated
@VisibleForTesting
public class TradeFormat {
@ -164,7 +165,7 @@ public class TradeFormat {
private static final Function<TradeInfo, String> amountFormat = (t) ->
t.getOffer().getBaseCurrencyCode().equals("BTC")
? formatSatoshis(t.getTradeAmountAsLong())
: formatCryptoCurrencyOfferVolume(t.getTradeVolume());
: formatCryptoCurrencyVolume(t.getTradeVolume());
private static final BiFunction<TradeInfo, Boolean, String> makerTakerMinerTxFeeFormat = (t, isTaker) -> {
if (isTaker) {
@ -188,7 +189,7 @@ public class TradeFormat {
private static final Function<TradeInfo, String> tradeCostFormat = (t) ->
t.getOffer().getBaseCurrencyCode().equals("BTC")
? formatOfferVolume(t.getTradeVolume())
? formatFiatVolume(t.getTradeVolume())
: formatSatoshis(t.getTradeAmountAsLong());
private static final BiFunction<TradeInfo, Boolean, String> bsqReceiveAddress = (t, showBsqBuyerAddress) -> {

View file

@ -25,6 +25,7 @@ import static bisq.cli.ColumnHeaderConstants.*;
import static bisq.cli.CurrencyFormat.formatSatoshis;
import static com.google.common.base.Strings.padEnd;
@Deprecated
@VisibleForTesting
public class TransactionFormat {