From 6f1057a7660f82c9c99c17f923a0d01b2036b69e Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:28:14 -0300 Subject: [PATCH 01/17] Include unmerged API NPE fix to FeeService class (see PR #6052) --- core/src/main/java/bisq/core/provider/fee/FeeService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/bisq/core/provider/fee/FeeService.java b/core/src/main/java/bisq/core/provider/fee/FeeService.java index e118d5f602f..ccb1da9670b 100644 --- a/core/src/main/java/bisq/core/provider/fee/FeeService.java +++ b/core/src/main/java/bisq/core/provider/fee/FeeService.java @@ -82,7 +82,7 @@ private static Coin getFeeFromParamAsCoin(Param param) { private static Coin getFilterFromParamAsCoin(Param param) { Coin filterVal = Coin.ZERO; - if (filterManager != null) { + if (filterManager != null && filterManager.getFilter() != null) { if (param == Param.DEFAULT_MAKER_FEE_BTC) { filterVal = Coin.valueOf(filterManager.getFilter().getMakerFeeBtc()); } else if (param == Param.DEFAULT_TAKER_FEE_BTC) { From 4596960191e5db3d61c20b36b8871d8a8a0e1a53 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:31:17 -0300 Subject: [PATCH 02/17] Prepare API Offers .proto defs for significant changes This commit adds comments to grpc.proto to be pulled into a new API reference doc. Some of the comments highlight issues to be resolved in following PRs. The main focus is on documenting gRPC Offers service definitions in grpc.proto: - Comment each field in the Offers service's messages. - Add TODO comments about fixing field defs with usability & consistency problems. Other API reference doc related changes to grpc.proto: - Comment each gRPC service's rpc method definitions, however briefly. - Improve some existing rpc method comments. --- proto/src/main/proto/grpc.proto | 224 ++++++++++++++++++++++---------- 1 file changed, 153 insertions(+), 71 deletions(-) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index b5530a890a2..0d4b0efc45d 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -22,79 +22,75 @@ option java_package = "bisq.proto.grpc"; option java_multiple_files = true; /* -* DisputeAgents service is provided for development, and can only be used when running in regtest mode. +* The DisputeAgents service is provided for development only; it can only be used when running in regtest mode. */ service DisputeAgents { - // Register regtest / dev mode dispute agents. Does not work if running on mainnet. + // Register regtest / dev mode dispute agents. Does not work when running on mainnet. rpc RegisterDisputeAgent (RegisterDisputeAgentRequest) returns (RegisterDisputeAgentReply) { } } -/* -* Register a dispute agent using a registration key. -*/ message RegisterDisputeAgentRequest { + // One of "mediator" or "refundagent". Development / test arbitrators can only be registered in the UI. string disputeAgentType = 1; + // Private developer (only) registration key. string registrationKey = 2; } message RegisterDisputeAgentReply { } - -/* -* CLI command help service. -*/ service Help { - // Returns CLI command help in man page format. + // Returns a CLI command man page. rpc GetMethodHelp (GetMethodHelpRequest) returns (GetMethodHelpReply) { } } message GetMethodHelpRequest { - string methodName = 1; + string methodName = 1; // CLI command name. } message GetMethodHelpReply { - string methodHelp = 1; + string methodHelp = 1; // Man page for CLI command. } - /* -* Offers service provides rpc methods for creating, editing, listing, and cancelling Bisq offers. +* The Offers service provides rpc methods for creating, editing, listing, and cancelling Bisq offers. */ service Offers { - // Get offer category, one of FIAT, ALTCOIN, or BSQ_SWAP. + // Get an offer's category, one of FIAT, ALTCOIN, or BSQ_SWAP. This information is needed before an offer + // can be taken, and is used by a client to determine what kind of offer to take: a v1 FIAT or ALTCOIN offer, + // or a BSQ swap offer. V1 and BSQ swap trades are handled differently in the API daemon. rpc GetOfferCategory (GetOfferCategoryRequest) returns (GetOfferCategoryReply) { } - // Get available BSQ swap offer with offer-id. + // Get the available BSQ swap offer with offer-id. rpc GetBsqSwapOffer (GetOfferRequest) returns (GetBsqSwapOfferReply) { } - // Get version 1 protocol offer with offer-id. + // Get the v1 protocol offer with offer-id. rpc GetOffer (GetOfferRequest) returns (GetOfferReply) { } - // Get my BSQ swap offer with offer-id. + // Get user's BSQ swap offer with offer-id. rpc GetMyBsqSwapOffer (GetMyOfferRequest) returns (GetMyBsqSwapOfferReply) { } - // Get my open version 1 protocol offer with offer-id. Deprecated since 27-Dec-2021 (v1.8.0). + // Get my open v1 protocol offer with offer-id. Deprecated since 27-Dec-2021 (v1.8.0). Use GetOffer. rpc GetMyOffer (GetMyOfferRequest) returns (GetMyOfferReply) { } - // Get available BSQ swap offers with direction BUY or SELL. + // Get all available BSQ swap offers with a BUY (BTC) or SELL (BTC) direction. rpc GetBsqSwapOffers (GetBsqSwapOffersRequest) returns (GetBsqSwapOffersReply) { } - // Get available version 1 protocol offers with direction BUY or SELL. + // Get all available v1 protocol offers with a BUY (BTC) or SELL (BTC) direction. rpc GetOffers (GetOffersRequest) returns (GetOffersReply) { } - // Get my BSQ swap offers with direction BUY or SELL. + // Get all user's BSQ swap offers with a BUY (BTC) or SELL (BTC) direction. rpc GetMyBsqSwapOffers (GetBsqSwapOffersRequest) returns (GetMyBsqSwapOffersReply) { } - // Get my open version 1 protocol offers with direction BUY or SELL. + // Get all user's open v1 protocol offers with a BUY (BTC) or SELL (BTC) direction. rpc GetMyOffers (GetMyOffersRequest) returns (GetMyOffersReply) { } // Create a BSQ swap offer. rpc CreateBsqSwapOffer (CreateBsqSwapOfferRequest) returns (CreateBsqSwapOfferReply) { } - // Create a version 1 protocol offer. + // Create a v1 protocol offer. rpc CreateOffer (CreateOfferRequest) returns (CreateOfferReply) { } // Edit an open offer. @@ -106,8 +102,8 @@ service Offers { } message GetOfferCategoryRequest { - string id = 1; - bool isMyOffer = 2; + string id = 1; // The offer's unique identifier. + bool isMyOffer = 2; // Whether the offer was created by the user or not. } message GetOfferCategoryReply { @@ -121,113 +117,154 @@ message GetOfferCategoryReply { } message GetBsqSwapOfferReply { - OfferInfo bsqSwapOffer = 1; + OfferInfo bsqSwapOffer = 1; // The returned BSQ swap offer. } message GetOfferRequest { - string id = 1; + string id = 1; // The offer's unique identifier. } message GetOfferReply { - OfferInfo offer = 1; + OfferInfo offer = 1; // The returned v1 protocol offer. } message GetMyBsqSwapOfferReply { - OfferInfo bsqSwapOffer = 1; + OfferInfo bsqSwapOffer = 1; // The returned BSQ swap offer. } -// @Deprecated since 27-Dec-2021 (v1.8.0) +// Deprecated with rpc method GetMyOffer since 27-Dec-2021 (v1.8.0). message GetMyOfferRequest { - string id = 1; + string id = 1; // The offer's unique identifier. } -// @Deprecated since 27-Dec-2021 (v1.8.0) +// Deprecated with rpc method GetMyOffer since 27-Dec-2021 (v1.8.0). message GetMyOfferReply { - OfferInfo offer = 1; + OfferInfo offer = 1; // The returned v1 protocol offer. } message GetOffersRequest { - string direction = 1; - string currencyCode = 2; + string direction = 1; // The offer's BUY (BTC) or SELL (BTC) direction. + string currencyCode = 2; // The offer's fiat or altcoin currency code. } message GetOffersReply { - repeated OfferInfo offers = 1; + repeated OfferInfo offers = 1; // The returned list of available offers. } message GetBsqSwapOffersRequest { - string direction = 1; + string direction = 1; // The BSQ swap offer's BUY (BTC) or SELL (BTC) direction. } message GetBsqSwapOffersReply { - repeated OfferInfo bsqSwapOffers = 1; + repeated OfferInfo bsqSwapOffers = 1; // The returned list of available BSQ swap offers. } message GetMyOffersRequest { - string direction = 1; - string currencyCode = 2; + string direction = 1; // The offers' BUY (BTC) or SELL (BTC) direction. + string currencyCode = 2; // The offer's fiat or altcoin currency code. } message GetMyOffersReply { - repeated OfferInfo offers = 1; + repeated OfferInfo offers = 1; // The returned list of user's open offers. } message GetMyBsqSwapOffersReply { - repeated OfferInfo bsqSwapOffers = 1; + repeated OfferInfo bsqSwapOffers = 1; // The returned list of user's open BSQ swap offers. } +// TODO: Use string for all number fields, in order to eliminate loss of precision or ambiguity. message CreateBsqSwapOfferRequest { + // The new BSQ swap offer's BUY (BTC) or SELL (BTC) direction. string direction = 1; + // The amount of BTC to be traded as a long representing satoshi units. uint64 amount = 2; + // The minimum amount of BTC to be traded as a long representing satoshi units. uint64 minAmount = 3; + // The fixed price of the offer as a string representing BTC units, e.g., "0.00005" or "0.00005000". string price = 4; } message CreateBsqSwapOfferReply { - OfferInfo bsqSwapOffer = 1; + OfferInfo bsqSwapOffer = 1; // The newly created BSQ swap offer. } +// TODO: Use string for all number fields, in order to eliminate loss of precision or ambiguity. message CreateOfferRequest { + // The new offer's fiat or altcoin currency code. string currencyCode = 1; + // The new v1 protocol offer's BUY (BTC) or SELL (BTC) direction. string direction = 2; + // For fiat offers: a string representing the rounded, fixed fiat price of the offer, e.g., "45000", not "45000". + // For altcoin offers: a string representing the fixed BTC price of the offer, e.g., "0.00005". string price = 3; + // Whether the offer price is fixed, or market price margin based. bool useMarketBasedPrice = 4; + // The offer's market price margin as a percentage above or below the current market BTC price, e.g., 2.50 represents 2.5%. double marketPriceMargin = 5; + // The amount of BTC to be traded, in satoshis. uint64 amount = 6; + // The minimum amount of BTC to be traded, in satoshis. uint64 minAmount = 7; + // For a new BUY BTC offer, the offer maker's security deposit as a percentage of the BTC amount to be traded, e.g., 0.15 represents 15%. + // TODO: This parameter (where 0.## represents ##%) conflicts with marketPriceMargin (where #.## literally represents #.##%). + // Backward compat breaking change to buyerSecurityDeposit is needed to make it consistent with marketPriceMargin (or vice-versa). double buyerSecurityDeposit = 8; + // For fiat, market price margin based offer, the current market BTC price at which the offer is automatically disabled. + // The parameter type is a long, representing the fiat price to 4 decimal places, but without the decimal. + // For example trigger price in EUR of 43749.3940 would be passed as 437493940. + // TODO: This should be a string type: "43749.3940", and converted to a long on the server. uint64 triggerPrice = 9; + // The unique identifier of the payment account used to create the new offer, and send or receive trade payment. string paymentAccountId = 10; + // The offer maker's trade fee currency: BTC or BSQ. string makerFeeCurrencyCode = 11; } message CreateOfferReply { - OfferInfo offer = 1; + OfferInfo offer = 1; // The newly created v1 protocol offer. } message EditOfferRequest { + // The edited offer's unique identifier. string id = 1; + // For fiat offers: a string representing the new rounded, fixed fiat price of the offer, e.g., "45000", not "45000". + // For altcoin offers: a string representing the new fixed BTC price of the offer, e.g., "0.00005". string price = 2; + // Whether the offer price is fixed, or market price margin based. bool useMarketBasedPrice = 3; + // The offer's new market price margin as a percentage above or below the current market BTC price. double marketPriceMargin = 4; + // For market price margin based offer, the current market BTC price at which the offer is automatically disabled. uint64 triggerPrice = 5; + // Whether the offer's activation state should be changed (disable or enable), or left alone. // Send a signed int, not a bool (with default=false). // -1 = do not change activation state // 0 = disable // 1 = enable sint32 enable = 6; - // The EditType constricts what offer details can be modified and simplifies param validation. + // The EditType determines and constricts what offer details can + // be modified by the request, simplifying param validation. enum EditType { - ACTIVATION_STATE_ONLY = 0; - FIXED_PRICE_ONLY = 1; - FIXED_PRICE_AND_ACTIVATION_STATE = 2; - MKT_PRICE_MARGIN_ONLY = 3; - MKT_PRICE_MARGIN_AND_ACTIVATION_STATE = 4; - TRIGGER_PRICE_ONLY = 5; - TRIGGER_PRICE_AND_ACTIVATION_STATE = 6; - MKT_PRICE_MARGIN_AND_TRIGGER_PRICE = 7; - MKT_PRICE_MARGIN_AND_TRIGGER_PRICE_AND_ACTIVATION_STATE = 8; - } + // Edit only the offer's activation state (enabled or disabled). + ACTIVATION_STATE_ONLY = 0; + // Edit only the offer's fixed price. + FIXED_PRICE_ONLY = 1; + // Edit only the offer's fixed price and activation state. + FIXED_PRICE_AND_ACTIVATION_STATE = 2; + // Edit only the offer's market price margin. + MKT_PRICE_MARGIN_ONLY = 3; + // Edit only the offer's market price margin and activation state. + MKT_PRICE_MARGIN_AND_ACTIVATION_STATE = 4; + // Edit only the market price margin based offer's trigger price. + TRIGGER_PRICE_ONLY = 5; + // Edit only the market price margin based offer's trigger price and activation state. + TRIGGER_PRICE_AND_ACTIVATION_STATE = 6; + // Edit only the offer's market price margin and trigger price. + MKT_PRICE_MARGIN_AND_TRIGGER_PRICE = 7; + // Edit only the offer's market price margin, trigger price, and activation state. + MKT_PRICE_MARGIN_AND_TRIGGER_PRICE_AND_ACTIVATION_STATE = 8; + } + // Tell the daemon precisely what is being edited. EditType editType = 7; } @@ -235,53 +272,106 @@ message EditOfferReply { } message CancelOfferRequest { - string id = 1; + string id = 1; // The canceled offer's unique identifier. } message CancelOfferReply { } +// OfferInfo describes an offer to a client. It is derived from the heavier +// Offer object in the daemon, which holds too much state to be sent to clients. +// TODO: Use string for all number fields, in order to eliminate loss of precision or ambiguity. message OfferInfo { + // The offer's unique identifier. string id = 1; + // The offer's BUY (BTC) or SELL (BTC) direction. string direction = 2; + // For fiat offers: a long representing the BTC price of the offer to 4 decimal places. + // A USD fiat price of 45000.4321 USD is represented as 450004321. + // For altcoin offers: a long representing the BTC price of the offer in satoshis. + // An altcoin price of five hundred thousand satoshis is represented as 500000. + // TODO: Change to string type. uint64 price = 3; + // Whether the offer price is fixed, or market price margin based. bool useMarketBasedPrice = 4; + // The offer's market price margin above or below the current market BTC price, represented as a decimal. + // 5% is represented as 0.05. + // TODO: Change to string type, and make consistent with Create & Edit Offer's marketPriceMargin params. double marketPriceMargin = 5; + // The offer's BTC amount in satoshis. Ten million satoshis is represented as 10000000. uint64 amount = 6; + // The offer's minimum BTC amount in satoshis. One million satoshis is represented as 1000000. uint64 minAmount = 7; + // A long representing the rounded volume of currency to be traded for BTC. + // For EUR fiat offers, a volume of 29500.000 EUR would be represented as 29500000. + // TODO: Seems to be a bug in the volume, missing one trailing decimal. + // Price has 4 "ghost" decimal places. Volume has only 3 "ghost" decimal places, e.g., + // EUR PRICE: 295001234 + // EUR VOL: 29500000 uint64 volume = 8; + // A long representing the minimum, rounded volume of currency to be traded for BTC. + // TODO: Resolve the problem mentioned above, in the volume field description. uint64 minVolume = 9; + // A long representing the BTC buyer's security deposit in satoshis. uint64 buyerSecurityDeposit = 10; + // A long representing a market price margin based offer's trigger price: the current market BTC price at + // which the offer is automatically disabled. For fiat offers, a trigger price of 40000.5000 is represented + // as 400005000. uint64 triggerPrice = 11; + // Whether the offer maker paid the trading fee in BTC or not (BSQ). bool isCurrencyForMakerFeeBtc = 12; + // The unique identifier of the payment account used to create the offer. string paymentAccountId = 13; + // The unique identifier of the payment method used to create the offer. string paymentMethodId = 14; + // The short description of the payment method used to create the offer. string paymentMethodShortName = 15; + // For fiat offers, the baseCurrencyCode is BTC, and the counterCurrencyCode is the fiat currency code. + // For altcoin offers it is the opposite, the baseCurrencyCode is the altcoin code and the counterCurrencyCode is BTC. string baseCurrencyCode = 16; + // For fiat offers, the baseCurrencyCode is BTC, and the counterCurrencyCode is the fiat currency code. + // For altcoin offers it is the opposite, the baseCurrencyCode is the altcoin code and the counterCurrencyCode is BTC. string counterCurrencyCode = 17; + // The creation date of the offer as a long: the number of milliseconds that have elapsed since January 1, 1970. uint64 date = 18; + // The internal state of the offer, e.g., AVAILABLE, NOT_AVAILABLE, REMOVED, etc. string state = 19; + // A long representing the BTC seller's security deposit in satoshis. uint64 sellerSecurityDeposit = 20; + // The bitcoin transaction id of the offer maker's fee payment. string offerFeePaymentTxId = 21; + // The bitcoin transaction fee (amount) for the offer maker's fee payment transaction, in satoshis. uint64 txFee = 22; + // The offer maker's Bisq trade fee amount in satoshis. uint64 makerFee = 23; + // Whether the offer is currently enabled or not. bool isActivated = 24; + // Whether the offer was created by the user or not. bool isMyOffer = 25; + // Whether the newly created offer was created by the user or not. bool isMyPendingOffer = 26; + // Whether the offer is a BSQ swap offer or not (v1 protocol offer). bool isBsqSwapOffer = 27; + // The offer creator's Tor onion address. string ownerNodeAddress = 28; + // The offer creator's public key ring as a string. string pubKeyRing = 29; + // The Bisq software version used to create the offer. string versionNr = 30; + // The bitcoin protocol version used to create the offer. int32 protocolVersion = 31; } +// An offer's current availability status. message AvailabilityResultWithDescription { + // An offer's current status as an eum. AvailabilityResult availabilityResult = 1; + // A user friendly description of an offer's current availability status. string description = 2; } /* -* PaymentAccounts service provides rpc methods for creating fiat and crypto currency payment accounts. +* The PaymentAccounts service provides rpc methods for creating fiat and crypto currency payment accounts. */ service PaymentAccounts { // Create a fiat payment account, providing details in a json form. @@ -352,11 +442,8 @@ message GetCryptoCurrencyPaymentMethodsReply { repeated PaymentMethod paymentMethods = 1; } -/* -* Price service comment. -*/ service Price { - // Get current market price for a crypto currency. + // Get the current market price for a crypto currency. rpc GetMarketPrice (MarketPriceRequest) returns (MarketPriceReply) { } } @@ -385,9 +472,6 @@ message GetTradeStatisticsReply { repeated TradeStatistics3 TradeStatistics = 1; } -/* -* ShutdownServer service comment. -*/ service ShutdownServer { // Shut down a local Bisq daemon. rpc Stop (StopRequest) returns (StopReply) { @@ -397,11 +481,12 @@ service ShutdownServer { message StopRequest { } + message StopReply { } /* -* Trades service provides rpc methods for taking, executing, and listing trades. +* The Trades service provides rpc methods for taking, executing, and listing trades. */ service Trades { // Get an open trade with a trade-id. @@ -601,7 +686,7 @@ message TxInfo { } /* -* Wallets service provides rpc methods for basic wallet operations such as checking balances, +* The Wallets service provides rpc methods for basic wallet operations such as checking balances, * sending BTC or BSQ to external wallets, checking transaction fee rates, setting or unsetting * an encryption password on a a wallet, and unlocking / locking an encrypted wallet. */ @@ -805,11 +890,8 @@ message AddressBalanceInfo { bool isAddressUnused = 4; } -/* -* GetVersion service provides the local Bisq daemon's version. -*/ service GetVersion { - // Get current Bisq version number. + // Get the current Bisq version number. rpc GetVersion (GetVersionRequest) returns (GetVersionReply) { } } From ddd3ec3243a869c79d8e723f5cafbd9d562aaa37 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 13:39:06 -0300 Subject: [PATCH 03/17] Fix comment about changing "all" number fields to string We will consider each problematic number field one at a time. Note: changing field types in following commits will break the API's backward compatibility, but devs agree it's OK since it is still in beta. --- proto/src/main/proto/grpc.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 0d4b0efc45d..f39ce446bb5 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -172,7 +172,7 @@ message GetMyBsqSwapOffersReply { repeated OfferInfo bsqSwapOffers = 1; // The returned list of user's open BSQ swap offers. } -// TODO: Use string for all number fields, in order to eliminate loss of precision or ambiguity. +// TODO: Change some numeric fields to string to prevent loss of precision and/or ambiguity. message CreateBsqSwapOfferRequest { // The new BSQ swap offer's BUY (BTC) or SELL (BTC) direction. string direction = 1; @@ -188,7 +188,7 @@ message CreateBsqSwapOfferReply { OfferInfo bsqSwapOffer = 1; // The newly created BSQ swap offer. } -// TODO: Use string for all number fields, in order to eliminate loss of precision or ambiguity. +// TODO: Change some numeric fields to string to prevent loss of precision and/or ambiguity. message CreateOfferRequest { // The new offer's fiat or altcoin currency code. string currencyCode = 1; @@ -280,7 +280,7 @@ message CancelOfferReply { // OfferInfo describes an offer to a client. It is derived from the heavier // Offer object in the daemon, which holds too much state to be sent to clients. -// TODO: Use string for all number fields, in order to eliminate loss of precision or ambiguity. +// TODO: Change some numeric fields to string to prevent loss of precision and/or ambiguity. message OfferInfo { // The offer's unique identifier. string id = 1; From 135a42ba4545ed5680904a1fcfd7698a78a0bdc9 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 15:00:52 -0300 Subject: [PATCH 04/17] Delete deprecated CLI console output formatting classes The new console output formatting (tbl) api is working, and the deprecated classes just add maintenance work. Update affected test cases. --- .../bisq/apitest/scenario/bot/RobotBob.java | 12 +- .../scenario/bot/protocol/BotProtocol.java | 11 +- .../bot/protocol/MakerBotProtocol.java | 12 +- .../bot/protocol/TakerBotProtocol.java | 5 +- .../java/bisq/cli/ColumnHeaderConstants.java | 81 ----- .../main/java/bisq/cli/DirectionFormat.java | 61 ---- cli/src/main/java/bisq/cli/OfferFormat.java | 309 ------------------ cli/src/main/java/bisq/cli/TableFormat.java | 156 --------- cli/src/main/java/bisq/cli/TradeFormat.java | 222 ------------- .../main/java/bisq/cli/TransactionFormat.java | 60 ---- .../cli/table/AddressCliOutputDiffTest.java | 17 +- .../table/GetBalanceCliOutputDiffTest.java | 15 +- .../cli/table/GetOffersCliOutputDiffTest.java | 9 +- .../cli/table/GetTradeCliOutputDiffTest.java | 9 +- .../GetTransactionCliOutputDiffTest.java | 10 +- .../PaymentAccountsCliOutputDiffTest.java | 9 +- 16 files changed, 65 insertions(+), 933 deletions(-) delete mode 100644 cli/src/main/java/bisq/cli/ColumnHeaderConstants.java delete mode 100644 cli/src/main/java/bisq/cli/DirectionFormat.java delete mode 100644 cli/src/main/java/bisq/cli/OfferFormat.java delete mode 100644 cli/src/main/java/bisq/cli/TableFormat.java delete mode 100644 cli/src/main/java/bisq/cli/TradeFormat.java delete mode 100644 cli/src/main/java/bisq/cli/TransactionFormat.java diff --git a/apitest/src/test/java/bisq/apitest/scenario/bot/RobotBob.java b/apitest/src/test/java/bisq/apitest/scenario/bot/RobotBob.java index d81f385a2ba..618b64c66ad 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/bot/RobotBob.java +++ b/apitest/src/test/java/bisq/apitest/scenario/bot/RobotBob.java @@ -22,7 +22,8 @@ import static bisq.apitest.scenario.bot.protocol.ProtocolStep.DONE; import static bisq.apitest.scenario.bot.shutdown.ManualShutdown.isShutdownCalled; -import static bisq.cli.TableFormat.formatBalancesTbls; +import static bisq.cli.table.builder.TableType.BSQ_BALANCE_TBL; +import static bisq.cli.table.builder.TableType.BTC_BALANCE_TBL; import static java.util.concurrent.TimeUnit.SECONDS; @@ -34,6 +35,7 @@ import bisq.apitest.scenario.bot.script.BashScriptGenerator; import bisq.apitest.scenario.bot.script.BotScript; import bisq.apitest.scenario.bot.shutdown.ManualBotShutdownException; +import bisq.cli.table.builder.TableBuilder; @Slf4j public @@ -74,10 +76,16 @@ public void run() { throw new IllegalStateException(botProtocol.getClass().getSimpleName() + " failed to complete."); } + StringBuilder balancesBuilder = new StringBuilder(); + balancesBuilder.append("BTC").append("\n"); + balancesBuilder.append(new TableBuilder(BTC_BALANCE_TBL, botClient.getBalance().getBtc()).build().toString()).append("\n"); + balancesBuilder.append("BSQ").append("\n"); + balancesBuilder.append(new TableBuilder(BSQ_BALANCE_TBL, botClient.getBalance().getBsq()).build().toString()); + log.info("Completed {} successful trade{}. Current Balance:\n{}", ++numTrades, numTrades == 1 ? "" : "s", - formatBalancesTbls(botClient.getBalance())); + balancesBuilder); if (numTrades < actions.length) { try { diff --git a/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/BotProtocol.java b/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/BotProtocol.java index b090742a917..3fde8c2715b 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/BotProtocol.java +++ b/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/BotProtocol.java @@ -39,6 +39,7 @@ import static bisq.apitest.scenario.bot.protocol.ProtocolStep.*; import static bisq.apitest.scenario.bot.shutdown.ManualShutdown.checkIfShutdownCalled; +import static bisq.cli.table.builder.TableType.TRADE_DETAIL_TBL; import static java.lang.String.format; import static java.lang.System.currentTimeMillis; import static java.util.Arrays.stream; @@ -50,7 +51,7 @@ import bisq.apitest.scenario.bot.BotClient; import bisq.apitest.scenario.bot.script.BashScriptGenerator; import bisq.apitest.scenario.bot.shutdown.ManualBotShutdownException; -import bisq.cli.TradeFormat; +import bisq.cli.table.builder.TableBuilder; @Slf4j public abstract class BotProtocol { @@ -133,7 +134,8 @@ protected void printBotProtocolStep() { try { var t = this.getBotClient().getTrade(trade.getTradeId()); if (t.getIsFiatSent()) { - log.info("Buyer has started payment for trade:\n{}", TradeFormat.format(t)); + log.info("Buyer has started payment for trade:\n{}", + new TableBuilder(TRADE_DETAIL_TBL, t).build().toString()); return t; } } catch (Exception ex) { @@ -167,7 +169,8 @@ protected void printBotProtocolStep() { try { var t = this.getBotClient().getTrade(trade.getTradeId()); if (t.getIsFiatReceived()) { - log.info("Seller has received payment for trade:\n{}", TradeFormat.format(t)); + log.info("Seller has received payment for trade:\n{}", + new TableBuilder(TRADE_DETAIL_TBL, t).build().toString()); return t; } } catch (Exception ex) { @@ -202,7 +205,7 @@ protected void printBotProtocolStep() { if (t.getIsPayoutPublished()) { log.info("Payout tx {} has been published for trade:\n{}", t.getPayoutTxId(), - TradeFormat.format(t)); + new TableBuilder(TRADE_DETAIL_TBL, t).build().toString()); return t; } } catch (Exception ex) { diff --git a/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/MakerBotProtocol.java b/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/MakerBotProtocol.java index 3f757dbbd28..a5ce8f5bcaf 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/MakerBotProtocol.java +++ b/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/MakerBotProtocol.java @@ -16,8 +16,8 @@ import static bisq.apitest.scenario.bot.protocol.ProtocolStep.DONE; import static bisq.apitest.scenario.bot.protocol.ProtocolStep.WAIT_FOR_OFFER_TAKER; import static bisq.apitest.scenario.bot.shutdown.ManualShutdown.checkIfShutdownCalled; -import static bisq.cli.OfferFormat.formatOfferTable; -import static java.util.Collections.singletonList; +import static bisq.cli.table.builder.TableType.OFFER_TBL; +import static bisq.cli.table.builder.TableType.TRADE_DETAIL_TBL; @@ -26,7 +26,7 @@ import bisq.apitest.scenario.bot.RandomOffer; import bisq.apitest.scenario.bot.script.BashScriptGenerator; import bisq.apitest.scenario.bot.shutdown.ManualBotShutdownException; -import bisq.cli.TradeFormat; +import bisq.cli.table.builder.TableBuilder; @Slf4j public class MakerBotProtocol extends BotProtocol { @@ -65,7 +65,7 @@ public void run() { private final Supplier randomOffer = () -> { checkIfShutdownCalled("Interrupted before creating random offer."); OfferInfo offer = new RandomOffer(botClient, paymentAccount).create().getOffer(); - log.info("Created random {} offer\n{}", currencyCode, formatOfferTable(singletonList(offer), currencyCode)); + log.info("Created random {} offer\n{}", currencyCode, new TableBuilder(OFFER_TBL, offer).build()); return offer; }; @@ -98,7 +98,9 @@ public void run() { private Optional getNewTrade(String offerId) { try { var trade = botClient.getTrade(offerId); - log.info("Offer {} was taken, new trade:\n{}", offerId, TradeFormat.format(trade)); + log.info("Offer {} was taken, new trade:\n{}", + offerId, + new TableBuilder(TRADE_DETAIL_TBL, trade).build().toString()); return Optional.of(trade); } catch (Exception ex) { // Get trade will throw a non-fatal gRPC exception if not found. diff --git a/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/TakerBotProtocol.java b/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/TakerBotProtocol.java index dd04b5c5bff..a0aba127d66 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/TakerBotProtocol.java +++ b/apitest/src/test/java/bisq/apitest/scenario/bot/protocol/TakerBotProtocol.java @@ -17,7 +17,7 @@ import static bisq.apitest.scenario.bot.protocol.ProtocolStep.FIND_OFFER; import static bisq.apitest.scenario.bot.protocol.ProtocolStep.TAKE_OFFER; import static bisq.apitest.scenario.bot.shutdown.ManualShutdown.checkIfShutdownCalled; -import static bisq.cli.OfferFormat.formatOfferTable; +import static bisq.cli.table.builder.TableType.OFFER_TBL; import static bisq.core.payment.payload.PaymentMethod.F2F_ID; @@ -26,6 +26,7 @@ import bisq.apitest.scenario.bot.BotClient; import bisq.apitest.scenario.bot.script.BashScriptGenerator; import bisq.apitest.scenario.bot.shutdown.ManualBotShutdownException; +import bisq.cli.table.builder.TableBuilder; @Slf4j public class TakerBotProtocol extends BotProtocol { @@ -64,7 +65,7 @@ public void run() { private final Supplier> firstOffer = () -> { var offers = botClient.getOffers(currencyCode); if (offers.size() > 0) { - log.info("Offers found:\n{}", formatOfferTable(offers, currencyCode)); + log.info("Offers found:\n{}", new TableBuilder(OFFER_TBL, offers).build()); OfferInfo offer = offers.get(0); log.info("Will take first offer {}", offer.getId()); return Optional.of(offer); diff --git a/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java b/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java deleted file mode 100644 index e71dde5eb1d..00000000000 --- a/cli/src/main/java/bisq/cli/ColumnHeaderConstants.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -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. - static final String COL_HEADER_DELIMITER = " "; - - // Table column header format specs, right padded with two spaces. In some cases - // such as COL_HEADER_CREATION_DATE, COL_HEADER_VOLUME and COL_HEADER_UUID, the - // expected max data string length is accounted for. In others, column header - // lengths are expected to be greater than any column value length. - static final String COL_HEADER_ADDRESS = padEnd("%-3s Address", 52, ' '); - static final String COL_HEADER_AMOUNT = "BTC(min - max)"; - static final String COL_HEADER_AVAILABLE_BALANCE = "Available Balance"; - static final String COL_HEADER_AVAILABLE_CONFIRMED_BALANCE = "Available Confirmed Balance"; - static final String COL_HEADER_UNCONFIRMED_CHANGE_BALANCE = "Unconfirmed Change Balance"; - static final String COL_HEADER_RESERVED_BALANCE = "Reserved Balance"; - static final String COL_HEADER_TOTAL_AVAILABLE_BALANCE = "Total Available Balance"; - static final String COL_HEADER_LOCKED_BALANCE = "Locked Balance"; - static final String COL_HEADER_LOCKED_FOR_VOTING_BALANCE = "Locked For Voting Balance"; - static final String COL_HEADER_LOCKUP_BONDS_BALANCE = "Lockup Bonds Balance"; - static final String COL_HEADER_UNLOCKING_BONDS_BALANCE = "Unlocking Bonds Balance"; - static final String COL_HEADER_UNVERIFIED_BALANCE = "Unverified Balance"; - static final String COL_HEADER_CONFIRMATIONS = "Confirmations"; - static final String COL_HEADER_IS_USED_ADDRESS = "Is Used"; - static final String COL_HEADER_CREATION_DATE = padEnd("Creation Date (UTC)", 20, ' '); - static final String COL_HEADER_CURRENCY = "Currency"; - static final String COL_HEADER_DIRECTION = "Buy/Sell"; - static final String COL_HEADER_ENABLED = "Enabled"; - static final String COL_HEADER_NAME = "Name"; - static final String COL_HEADER_PAYMENT_METHOD = "Payment Method"; - static final String COL_HEADER_PRICE = "Price in %-3s for 1 BTC"; - static final String COL_HEADER_PRICE_OF_ALTCOIN = "Price in BTC for 1 %-3s"; - static final String COL_HEADER_TRADE_AMOUNT = padStart("Amount(%-3s)", 12, ' '); - static final String COL_HEADER_TRADE_BSQ_BUYER_ADDRESS = "BSQ Buyer Address"; - static final String COL_HEADER_TRADE_BUYER_COST = padEnd("Buyer Cost(%-3s)", 15, ' '); - static final String COL_HEADER_TRADE_DEPOSIT_CONFIRMED = "Deposit Confirmed"; - static final String COL_HEADER_TRADE_DEPOSIT_PUBLISHED = "Deposit Published"; - static final String COL_HEADER_TRADE_PAYMENT_SENT = padEnd("%-3s Sent", 8, ' '); - static final String COL_HEADER_TRADE_PAYMENT_RECEIVED = padEnd("%-3s Received", 12, ' '); - static final String COL_HEADER_TRADE_PAYOUT_PUBLISHED = "Payout Published"; - static final String COL_HEADER_TRADE_WITHDRAWN = "Withdrawn"; - static final String COL_HEADER_TRADE_ROLE = "My Role"; - static final String COL_HEADER_TRADE_SHORT_ID = "ID"; - static final String COL_HEADER_TRADE_TX_FEE = padEnd("Tx Fee(BTC)", 12, ' '); - static final String COL_HEADER_TRADE_MAKER_FEE = padEnd("Maker Fee(%-3s)", 12, ' '); // "Maker Fee(%-3s)"; - static final String COL_HEADER_TRADE_TAKER_FEE = padEnd("Taker Fee(%-3s)", 12, ' '); // "Taker Fee(%-3s)"; - static final String COL_HEADER_TRIGGER_PRICE = "Trigger Price(%-3s)"; - static final String COL_HEADER_TX_ID = "Tx ID"; - static final String COL_HEADER_TX_INPUT_SUM = "Tx Inputs (BTC)"; - static final String COL_HEADER_TX_OUTPUT_SUM = "Tx Outputs (BTC)"; - static final String COL_HEADER_TX_FEE = "Tx Fee (BTC)"; - static final String COL_HEADER_TX_SIZE = "Tx Size (Bytes)"; - static final String COL_HEADER_TX_IS_CONFIRMED = "Is Confirmed"; - static final String COL_HEADER_TX_MEMO = "Memo"; - - static final String COL_HEADER_VOLUME = padEnd("%-3s(min - max)", 15, ' '); - - static final String COL_HEADER_UUID = padEnd("ID", 52, ' '); -} diff --git a/cli/src/main/java/bisq/cli/DirectionFormat.java b/cli/src/main/java/bisq/cli/DirectionFormat.java deleted file mode 100644 index c56d89467b1..00000000000 --- a/cli/src/main/java/bisq/cli/DirectionFormat.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.cli; - -import bisq.proto.grpc.OfferInfo; - -import java.util.List; -import java.util.function.Function; - -import static bisq.cli.ColumnHeaderConstants.COL_HEADER_DIRECTION; -import static java.lang.String.format; -import static protobuf.OfferDirection.BUY; -import static protobuf.OfferDirection.SELL; - -@Deprecated -class DirectionFormat { - - static int getLongestDirectionColWidth(List offers) { - if (offers.isEmpty() || offers.get(0).getBaseCurrencyCode().equals("BTC")) - return COL_HEADER_DIRECTION.length(); - else - return 18; // .e.g., "Sell BSQ (Buy BTC)".length() - } - - static final Function directionFormat = (offer) -> { - String baseCurrencyCode = offer.getBaseCurrencyCode(); - boolean isCryptoCurrencyOffer = !baseCurrencyCode.equals("BTC"); - if (!isCryptoCurrencyOffer) { - return baseCurrencyCode; - } else { - // Return "Sell BSQ (Buy BTC)", or "Buy BSQ (Sell BTC)". - String direction = offer.getDirection(); - String mirroredDirection = getMirroredDirection(direction); - Function mixedCase = (word) -> word.charAt(0) + word.substring(1).toLowerCase(); - return format("%s %s (%s %s)", - mixedCase.apply(mirroredDirection), - baseCurrencyCode, - mixedCase.apply(direction), - offer.getCounterCurrencyCode()); - } - }; - - static String getMirroredDirection(String directionAsString) { - return directionAsString.equalsIgnoreCase(BUY.name()) ? SELL.name() : BUY.name(); - } -} diff --git a/cli/src/main/java/bisq/cli/OfferFormat.java b/cli/src/main/java/bisq/cli/OfferFormat.java deleted file mode 100644 index 9aea2d91673..00000000000 --- a/cli/src/main/java/bisq/cli/OfferFormat.java +++ /dev/null @@ -1,309 +0,0 @@ -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 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 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 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 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 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 offers) { - return getLongestColumnSize( - COL_HEADER_PAYMENT_METHOD.length(), - offers.stream() - .map(OfferInfo::getPaymentMethodShortName) - .collect(Collectors.toList())); - } - - private static int getLongestAmountColWidth(List offers) { - return getLongestColumnSize( - COL_HEADER_AMOUNT.length(), - offers.stream() - .map(o -> formatAmountRange(o.getMinAmount(), o.getAmount())) - .collect(Collectors.toList())); - } - - private static int getLongestVolumeColWidth(List 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 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())); - } -} diff --git a/cli/src/main/java/bisq/cli/TableFormat.java b/cli/src/main/java/bisq/cli/TableFormat.java deleted file mode 100644 index 37c3b36476c..00000000000 --- a/cli/src/main/java/bisq/cli/TableFormat.java +++ /dev/null @@ -1,156 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.cli; - -import bisq.proto.grpc.AddressBalanceInfo; -import bisq.proto.grpc.BalancesInfo; -import bisq.proto.grpc.BsqBalanceInfo; -import bisq.proto.grpc.BtcBalanceInfo; - -import protobuf.PaymentAccount; - -import com.google.common.annotations.VisibleForTesting; - -import java.text.SimpleDateFormat; - -import java.util.Date; -import java.util.List; -import java.util.TimeZone; -import java.util.stream.Collectors; - -import static bisq.cli.ColumnHeaderConstants.*; -import static bisq.cli.CurrencyFormat.formatBsq; -import static bisq.cli.CurrencyFormat.formatSatoshis; -import static com.google.common.base.Strings.padEnd; -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 { - - static final TimeZone TZ_UTC = getTimeZone("UTC"); - static final SimpleDateFormat DATE_FORMAT_ISO_8601 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - - public static String formatAddressBalanceTbl(List addressBalanceInfo) { - String headerFormatString = COL_HEADER_ADDRESS + COL_HEADER_DELIMITER - + COL_HEADER_AVAILABLE_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_CONFIRMATIONS + COL_HEADER_DELIMITER - + COL_HEADER_IS_USED_ADDRESS + COL_HEADER_DELIMITER + "\n"; - String headerLine = format(headerFormatString, "BTC"); - - String colDataFormat = "%-" + COL_HEADER_ADDRESS.length() + "s" // lt justify - + " %" + (COL_HEADER_AVAILABLE_BALANCE.length() - 1) + "s" // rt justify - + " %" + COL_HEADER_CONFIRMATIONS.length() + "d" // rt justify - + " %-" + COL_HEADER_IS_USED_ADDRESS.length() + "s"; // lt justify - return headerLine - + addressBalanceInfo.stream() - .map(info -> format(colDataFormat, - info.getAddress(), - formatSatoshis(info.getBalance()), - info.getNumConfirmations(), - info.getIsAddressUnused() ? "NO" : "YES")) - .collect(Collectors.joining("\n")); - } - - public static String formatBalancesTbls(BalancesInfo balancesInfo) { - return "BTC" + "\n" - + formatBtcBalanceInfoTbl(balancesInfo.getBtc()) + "\n" - + "BSQ" + "\n" - + formatBsqBalanceInfoTbl(balancesInfo.getBsq()); - } - - public static String formatBsqBalanceInfoTbl(BsqBalanceInfo bsqBalanceInfo) { - String headerLine = COL_HEADER_AVAILABLE_CONFIRMED_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_UNVERIFIED_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_UNCONFIRMED_CHANGE_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_LOCKED_FOR_VOTING_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_LOCKUP_BONDS_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_UNLOCKING_BONDS_BALANCE + COL_HEADER_DELIMITER + "\n"; - String colDataFormat = "%" + COL_HEADER_AVAILABLE_CONFIRMED_BALANCE.length() + "s" // rt justify - + " %" + (COL_HEADER_UNVERIFIED_BALANCE.length() + 1) + "s" // rt justify - + " %" + (COL_HEADER_UNCONFIRMED_CHANGE_BALANCE.length() + 1) + "s" // rt justify - + " %" + (COL_HEADER_LOCKED_FOR_VOTING_BALANCE.length() + 1) + "s" // rt justify - + " %" + (COL_HEADER_LOCKUP_BONDS_BALANCE.length() + 1) + "s" // rt justify - + " %" + (COL_HEADER_UNLOCKING_BONDS_BALANCE.length() + 1) + "s"; // rt justify - return headerLine + format(colDataFormat, - formatBsq(bsqBalanceInfo.getAvailableConfirmedBalance()), - formatBsq(bsqBalanceInfo.getUnverifiedBalance()), - formatBsq(bsqBalanceInfo.getUnconfirmedChangeBalance()), - formatBsq(bsqBalanceInfo.getLockedForVotingBalance()), - formatBsq(bsqBalanceInfo.getLockupBondsBalance()), - formatBsq(bsqBalanceInfo.getUnlockingBondsBalance())); - } - - public static String formatBtcBalanceInfoTbl(BtcBalanceInfo btcBalanceInfo) { - String headerLine = COL_HEADER_AVAILABLE_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_RESERVED_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_TOTAL_AVAILABLE_BALANCE + COL_HEADER_DELIMITER - + COL_HEADER_LOCKED_BALANCE + COL_HEADER_DELIMITER + "\n"; - String colDataFormat = "%" + COL_HEADER_AVAILABLE_BALANCE.length() + "s" // rt justify - + " %" + (COL_HEADER_RESERVED_BALANCE.length() + 1) + "s" // rt justify - + " %" + (COL_HEADER_TOTAL_AVAILABLE_BALANCE.length() + 1) + "s" // rt justify - + " %" + (COL_HEADER_LOCKED_BALANCE.length() + 1) + "s"; // rt justify - return headerLine + format(colDataFormat, - formatSatoshis(btcBalanceInfo.getAvailableBalance()), - formatSatoshis(btcBalanceInfo.getReservedBalance()), - formatSatoshis(btcBalanceInfo.getTotalAvailableBalance()), - formatSatoshis(btcBalanceInfo.getLockedBalance())); - } - - public static String formatPaymentAcctTbl(List paymentAccounts) { - // Some column values might be longer than header, so we need to calculate them. - int nameColWidth = getLongestColumnSize( - COL_HEADER_NAME.length(), - paymentAccounts.stream().map(PaymentAccount::getAccountName) - .collect(Collectors.toList())); - int paymentMethodColWidth = getLongestColumnSize( - COL_HEADER_PAYMENT_METHOD.length(), - paymentAccounts.stream().map(a -> a.getPaymentMethod().getId()) - .collect(Collectors.toList())); - String headerLine = padEnd(COL_HEADER_NAME, nameColWidth, ' ') + COL_HEADER_DELIMITER - + COL_HEADER_CURRENCY + COL_HEADER_DELIMITER - + padEnd(COL_HEADER_PAYMENT_METHOD, paymentMethodColWidth, ' ') + COL_HEADER_DELIMITER - + COL_HEADER_UUID + COL_HEADER_DELIMITER + "\n"; - String colDataFormat = "%-" + nameColWidth + "s" // left justify - + " %-" + COL_HEADER_CURRENCY.length() + "s" // left justify - + " %-" + paymentMethodColWidth + "s" // left justify - + " %-" + COL_HEADER_UUID.length() + "s"; // left justify - return headerLine - + paymentAccounts.stream() - .map(a -> format(colDataFormat, - a.getAccountName(), - a.getSelectedTradeCurrency().getCode(), - a.getPaymentMethod().getId(), - a.getId())) - .collect(Collectors.joining("\n")); - } - - // Return size of the longest string value, or the header.len, whichever is greater. - static int getLongestColumnSize(int headerLength, List strings) { - int longest = max(strings, comparing(String::length)).length(); - return Math.max(longest, headerLength); - } - - static String formatTimestamp(long timestamp) { - DATE_FORMAT_ISO_8601.setTimeZone(TZ_UTC); - return DATE_FORMAT_ISO_8601.format(new Date(timestamp)); - } -} diff --git a/cli/src/main/java/bisq/cli/TradeFormat.java b/cli/src/main/java/bisq/cli/TradeFormat.java deleted file mode 100644 index 4ac85497288..00000000000 --- a/cli/src/main/java/bisq/cli/TradeFormat.java +++ /dev/null @@ -1,222 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.cli; - -import bisq.proto.grpc.ContractInfo; -import bisq.proto.grpc.TradeInfo; - -import com.google.common.annotations.VisibleForTesting; - -import java.util.function.BiFunction; -import java.util.function.Function; -import java.util.function.Supplier; - -import static bisq.cli.ColumnHeaderConstants.*; -import static bisq.cli.CurrencyFormat.*; -import static com.google.common.base.Strings.padEnd; - -@Deprecated -@VisibleForTesting -public class TradeFormat { - - private static final String YES = "YES"; - private static final String NO = "NO"; - - // TODO add String format(List trades) - - @VisibleForTesting - public static String format(TradeInfo tradeInfo) { - // Some column values might be longer than header, so we need to calculate them. - int shortIdColWidth = Math.max(COL_HEADER_TRADE_SHORT_ID.length(), tradeInfo.getShortId().length()); - int roleColWidth = Math.max(COL_HEADER_TRADE_ROLE.length(), tradeInfo.getRole().length()); - - // We only show taker fee under its header when user is the taker. - boolean isTaker = tradeInfo.getRole().toLowerCase().contains("taker"); - Supplier makerFeeHeader = () -> !isTaker ? - COL_HEADER_TRADE_MAKER_FEE + COL_HEADER_DELIMITER - : ""; - Supplier makerFeeHeaderSpec = () -> !isTaker ? - "%" + (COL_HEADER_TRADE_MAKER_FEE.length() + 2) + "s" - : ""; - Supplier takerFeeHeader = () -> isTaker ? - COL_HEADER_TRADE_TAKER_FEE + COL_HEADER_DELIMITER - : ""; - Supplier takerFeeHeaderSpec = () -> isTaker ? - "%" + (COL_HEADER_TRADE_TAKER_FEE.length() + 2) + "s" - : ""; - - boolean showBsqBuyerAddress = shouldShowBsqBuyerAddress(tradeInfo, isTaker); - Supplier bsqBuyerAddressHeader = () -> showBsqBuyerAddress ? COL_HEADER_TRADE_BSQ_BUYER_ADDRESS : ""; - Supplier bsqBuyerAddressHeaderSpec = () -> showBsqBuyerAddress ? "%s" : ""; - - String headersFormat = padEnd(COL_HEADER_TRADE_SHORT_ID, shortIdColWidth, ' ') + COL_HEADER_DELIMITER - + padEnd(COL_HEADER_TRADE_ROLE, roleColWidth, ' ') + COL_HEADER_DELIMITER - + priceHeader.apply(tradeInfo) + COL_HEADER_DELIMITER // includes %s -> currencyCode - + padEnd(COL_HEADER_TRADE_AMOUNT, 12, ' ') + COL_HEADER_DELIMITER - + padEnd(COL_HEADER_TRADE_TX_FEE, 12, ' ') + COL_HEADER_DELIMITER - + makerFeeHeader.get() - // maker or taker fee header, not both - + takerFeeHeader.get() - + COL_HEADER_TRADE_DEPOSIT_PUBLISHED + COL_HEADER_DELIMITER - + COL_HEADER_TRADE_DEPOSIT_CONFIRMED + COL_HEADER_DELIMITER - + COL_HEADER_TRADE_BUYER_COST + COL_HEADER_DELIMITER - + COL_HEADER_TRADE_PAYMENT_SENT + COL_HEADER_DELIMITER - + COL_HEADER_TRADE_PAYMENT_RECEIVED + COL_HEADER_DELIMITER - + COL_HEADER_TRADE_PAYOUT_PUBLISHED + COL_HEADER_DELIMITER - + COL_HEADER_TRADE_WITHDRAWN + COL_HEADER_DELIMITER - + bsqBuyerAddressHeader.get() - + "%n"; - - String counterCurrencyCode = tradeInfo.getOffer().getCounterCurrencyCode(); - String baseCurrencyCode = tradeInfo.getOffer().getBaseCurrencyCode(); - - String headerLine = String.format(headersFormat, - /* COL_HEADER_PRICE */ priceHeaderCurrencyCode.apply(tradeInfo), - /* COL_HEADER_TRADE_AMOUNT */ baseCurrencyCode, - /* COL_HEADER_TRADE_(M||T)AKER_FEE */ makerTakerFeeHeaderCurrencyCode.apply(tradeInfo, isTaker), - /* COL_HEADER_TRADE_BUYER_COST */ counterCurrencyCode, - /* COL_HEADER_TRADE_PAYMENT_SENT */ paymentStatusHeaderCurrencyCode.apply(tradeInfo), - /* COL_HEADER_TRADE_PAYMENT_RECEIVED */ paymentStatusHeaderCurrencyCode.apply(tradeInfo)); - - String colDataFormat = "%-" + shortIdColWidth + "s" // lt justify - + " %-" + (roleColWidth + COL_HEADER_DELIMITER.length()) + "s" // left - + "%" + (COL_HEADER_PRICE.length() - 1) + "s" // rt justify - + "%" + (COL_HEADER_TRADE_AMOUNT.length() + 1) + "s" // rt justify - + "%" + (COL_HEADER_TRADE_TX_FEE.length() + 1) + "s" // rt justify - + makerFeeHeaderSpec.get() // rt justify - // OR (one of them is an empty string) - + takerFeeHeaderSpec.get() // rt justify - + " %-" + COL_HEADER_TRADE_DEPOSIT_PUBLISHED.length() + "s" // lt justify - + " %-" + COL_HEADER_TRADE_DEPOSIT_CONFIRMED.length() + "s" // lt justify - + "%" + (COL_HEADER_TRADE_BUYER_COST.length() + 1) + "s" // rt justify - + " %-" + (COL_HEADER_TRADE_PAYMENT_SENT.length() - 1) + "s" // left - + " %-" + (COL_HEADER_TRADE_PAYMENT_RECEIVED.length() - 1) + "s" // left - + " %-" + COL_HEADER_TRADE_PAYOUT_PUBLISHED.length() + "s" // lt justify - + " %-" + (COL_HEADER_TRADE_WITHDRAWN.length() + 2) + "s" - + bsqBuyerAddressHeaderSpec.get(); - - return headerLine + formatTradeData(colDataFormat, tradeInfo, isTaker, showBsqBuyerAddress); - } - - private static String formatTradeData(String format, - TradeInfo tradeInfo, - boolean isTaker, - boolean showBsqBuyerAddress) { - return String.format(format, - tradeInfo.getShortId(), - tradeInfo.getRole(), - priceFormat.apply(tradeInfo), - amountFormat.apply(tradeInfo), - makerTakerMinerTxFeeFormat.apply(tradeInfo, isTaker), - makerTakerFeeFormat.apply(tradeInfo, isTaker), - tradeInfo.getIsDepositPublished() ? YES : NO, - tradeInfo.getIsDepositConfirmed() ? YES : NO, - tradeCostFormat.apply(tradeInfo), - tradeInfo.getIsFiatSent() ? YES : NO, - tradeInfo.getIsFiatReceived() ? YES : NO, - tradeInfo.getIsPayoutPublished() ? YES : NO, - tradeInfo.getIsWithdrawn() ? YES : NO, - bsqReceiveAddress.apply(tradeInfo, showBsqBuyerAddress)); - } - - private static final Function priceHeader = (t) -> - t.getOffer().getBaseCurrencyCode().equals("BTC") - ? COL_HEADER_PRICE - : COL_HEADER_PRICE_OF_ALTCOIN; - - private static final Function priceHeaderCurrencyCode = (t) -> - t.getOffer().getBaseCurrencyCode().equals("BTC") - ? t.getOffer().getCounterCurrencyCode() - : t.getOffer().getBaseCurrencyCode(); - - private static final BiFunction makerTakerFeeHeaderCurrencyCode = (t, isTaker) -> { - if (isTaker) { - return t.getIsCurrencyForTakerFeeBtc() ? "BTC" : "BSQ"; - } else { - return t.getOffer().getIsCurrencyForMakerFeeBtc() ? "BTC" : "BSQ"; - } - }; - - private static final Function paymentStatusHeaderCurrencyCode = (t) -> - t.getOffer().getBaseCurrencyCode().equals("BTC") - ? t.getOffer().getCounterCurrencyCode() - : t.getOffer().getBaseCurrencyCode(); - - private static final Function priceFormat = (t) -> - t.getOffer().getBaseCurrencyCode().equals("BTC") - ? formatPrice(t.getTradePrice()) - : formatCryptoCurrencyPrice(t.getTradePrice()); - - private static final Function amountFormat = (t) -> - t.getOffer().getBaseCurrencyCode().equals("BTC") - ? formatSatoshis(t.getTradeAmountAsLong()) - : formatCryptoCurrencyVolume(t.getTradeVolume()); - - private static final BiFunction makerTakerMinerTxFeeFormat = (t, isTaker) -> { - if (isTaker) { - return formatSatoshis(t.getTxFeeAsLong()); - } else { - return formatSatoshis(t.getOffer().getTxFee()); - } - }; - - private static final BiFunction makerTakerFeeFormat = (t, isTaker) -> { - if (isTaker) { - return t.getIsCurrencyForTakerFeeBtc() - ? formatSatoshis(t.getTakerFeeAsLong()) - : formatBsq(t.getTakerFeeAsLong()); - } else { - return t.getOffer().getIsCurrencyForMakerFeeBtc() - ? formatSatoshis(t.getOffer().getMakerFee()) - : formatBsq(t.getOffer().getMakerFee()); - } - }; - - private static final Function tradeCostFormat = (t) -> - t.getOffer().getBaseCurrencyCode().equals("BTC") - ? formatFiatVolume(t.getTradeVolume()) - : formatSatoshis(t.getTradeAmountAsLong()); - - private static final BiFunction bsqReceiveAddress = (t, showBsqBuyerAddress) -> { - if (showBsqBuyerAddress) { - ContractInfo contract = t.getContract(); - boolean isBuyerMakerAndSellerTaker = contract.getIsBuyerMakerAndSellerTaker(); - return isBuyerMakerAndSellerTaker // (is BTC buyer / maker) - ? contract.getTakerPaymentAccountPayload().getAddress() - : contract.getMakerPaymentAccountPayload().getAddress(); - } else { - return ""; - } - }; - - private static boolean shouldShowBsqBuyerAddress(TradeInfo tradeInfo, boolean isTaker) { - if (tradeInfo.getOffer().getBaseCurrencyCode().equals("BTC")) { - return false; - } else { - ContractInfo contract = tradeInfo.getContract(); - // Do not forget buyer and seller refer to BTC buyer and seller, not BSQ - // buyer and seller. If you are buying BSQ, you are the (BTC) seller. - boolean isBuyerMakerAndSellerTaker = contract.getIsBuyerMakerAndSellerTaker(); - if (isTaker) { - return !isBuyerMakerAndSellerTaker; - } else { - return isBuyerMakerAndSellerTaker; - } - } - } -} diff --git a/cli/src/main/java/bisq/cli/TransactionFormat.java b/cli/src/main/java/bisq/cli/TransactionFormat.java deleted file mode 100644 index fd0553c537a..00000000000 --- a/cli/src/main/java/bisq/cli/TransactionFormat.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of Bisq. - * - * Bisq is free software: you can redistribute it and/or modify it - * under the terms of the GNU Affero General Public License as published by - * the Free Software Foundation, either version 3 of the License, or (at - * your option) any later version. - * - * Bisq is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public - * License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with Bisq. If not, see . - */ - -package bisq.cli; - -import bisq.proto.grpc.TxInfo; - -import com.google.common.annotations.VisibleForTesting; - -import static bisq.cli.ColumnHeaderConstants.*; -import static bisq.cli.CurrencyFormat.formatSatoshis; -import static com.google.common.base.Strings.padEnd; - -@Deprecated -@VisibleForTesting -public class TransactionFormat { - - public static String format(TxInfo txInfo) { - String headerLine = padEnd(COL_HEADER_TX_ID, txInfo.getTxId().length(), ' ') + COL_HEADER_DELIMITER - + COL_HEADER_TX_IS_CONFIRMED + COL_HEADER_DELIMITER - + COL_HEADER_TX_INPUT_SUM + COL_HEADER_DELIMITER - + COL_HEADER_TX_OUTPUT_SUM + COL_HEADER_DELIMITER - + COL_HEADER_TX_FEE + COL_HEADER_DELIMITER - + COL_HEADER_TX_SIZE + COL_HEADER_DELIMITER - + (txInfo.getMemo().isEmpty() ? "" : COL_HEADER_TX_MEMO + COL_HEADER_DELIMITER) - + "\n"; - - String colDataFormat = "%-" + txInfo.getTxId().length() + "s" - + " %" + COL_HEADER_TX_IS_CONFIRMED.length() + "s" - + " %" + COL_HEADER_TX_INPUT_SUM.length() + "s" - + " %" + COL_HEADER_TX_OUTPUT_SUM.length() + "s" - + " %" + COL_HEADER_TX_FEE.length() + "s" - + " %" + COL_HEADER_TX_SIZE.length() + "s" - + " %s"; - - return headerLine - + String.format(colDataFormat, - txInfo.getTxId(), - txInfo.getIsPending() ? "NO" : "YES", // pending=true means not confirmed - formatSatoshis(txInfo.getInputSum()), - formatSatoshis(txInfo.getOutputSum()), - formatSatoshis(txInfo.getFee()), - txInfo.getSize(), - txInfo.getMemo().isEmpty() ? "" : txInfo.getMemo()); - } -} diff --git a/cli/src/test/java/bisq/cli/table/AddressCliOutputDiffTest.java b/cli/src/test/java/bisq/cli/table/AddressCliOutputDiffTest.java index 2f8c8542cff..be5fd9de87e 100644 --- a/cli/src/test/java/bisq/cli/table/AddressCliOutputDiffTest.java +++ b/cli/src/test/java/bisq/cli/table/AddressCliOutputDiffTest.java @@ -11,7 +11,6 @@ import bisq.cli.AbstractCliTest; -import bisq.cli.TableFormat; import bisq.cli.table.builder.TableBuilder; @SuppressWarnings("unused") @@ -30,11 +29,13 @@ public AddressCliOutputDiffTest() { private void getFundingAddresses() { var fundingAddresses = aliceClient.getFundingAddresses(); if (fundingAddresses.size() > 0) { - var oldTbl = TableFormat.formatAddressBalanceTbl(fundingAddresses); + // TableFormat class had been deprecated, then deleted on 17-Feb-2022, but + // these diff tests can be useful for testing changes to the current tbl formatting api. + // var oldTbl = TableFormat.formatAddressBalanceTbl(fundingAddresses); var newTbl = new TableBuilder(ADDRESS_BALANCE_TBL, fundingAddresses).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } else { err.println("no funding addresses found"); } @@ -52,10 +53,12 @@ private void getAddressBalance() { private void getAddressBalance(String address) { var addressBalance = singletonList(aliceClient.getAddressBalance(address)); - var oldTbl = TableFormat.formatAddressBalanceTbl(addressBalance); + // TableFormat class had been deprecated, then deleted on 17-Feb-2022, but these + // diff tests can be useful for testing changes to the current tbl formatting api. + // var oldTbl = TableFormat.formatAddressBalanceTbl(addressBalance); var newTbl = new TableBuilder(ADDRESS_BALANCE_TBL, addressBalance).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } } diff --git a/cli/src/test/java/bisq/cli/table/GetBalanceCliOutputDiffTest.java b/cli/src/test/java/bisq/cli/table/GetBalanceCliOutputDiffTest.java index 0fa6d11c3da..d59e87004c2 100644 --- a/cli/src/test/java/bisq/cli/table/GetBalanceCliOutputDiffTest.java +++ b/cli/src/test/java/bisq/cli/table/GetBalanceCliOutputDiffTest.java @@ -6,7 +6,6 @@ import bisq.cli.AbstractCliTest; -import bisq.cli.TableFormat; import bisq.cli.table.builder.TableBuilder; @SuppressWarnings("unused") @@ -24,19 +23,21 @@ public GetBalanceCliOutputDiffTest() { private void getBtcBalance() { var balance = aliceClient.getBtcBalances(); - var oldTbl = TableFormat.formatBtcBalanceInfoTbl(balance); + // TableFormat class had been deprecated, then deleted on 17-Feb-2022, but these + // diff tests can be useful for testing changes to the current tbl formatting api. + // var oldTbl = TableFormat.formatBtcBalanceInfoTbl(balance); var newTbl = new TableBuilder(BTC_BALANCE_TBL, balance).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } private void getBsqBalance() { var balance = aliceClient.getBsqBalances(); - var oldTbl = TableFormat.formatBsqBalanceInfoTbl(balance); + // var oldTbl = TableFormat.formatBsqBalanceInfoTbl(balance); var newTbl = new TableBuilder(BSQ_BALANCE_TBL, balance).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } } diff --git a/cli/src/test/java/bisq/cli/table/GetOffersCliOutputDiffTest.java b/cli/src/test/java/bisq/cli/table/GetOffersCliOutputDiffTest.java index d97c9f8ded2..f5b85bdc62b 100644 --- a/cli/src/test/java/bisq/cli/table/GetOffersCliOutputDiffTest.java +++ b/cli/src/test/java/bisq/cli/table/GetOffersCliOutputDiffTest.java @@ -13,7 +13,6 @@ import bisq.cli.AbstractCliTest; -import bisq.cli.OfferFormat; import bisq.cli.table.builder.TableBuilder; @SuppressWarnings("unused") @@ -116,11 +115,13 @@ private void printAndCheckDiffs(List offers, log.warn("No {} {} offers to print.", direction, currencyCode); } else { log.info("Checking for diffs in {} {} offers.", direction, currencyCode); - var oldTbl = OfferFormat.formatOfferTable(offers, currencyCode); + // OfferFormat class had been deprecated, then deleted on 17-Feb-2022, but + // these diff tests can be useful for testing changes to the current tbl formatting api. + // var oldTbl = OfferFormat.formatOfferTable(offers, currencyCode); var newTbl = new TableBuilder(OFFER_TBL, offers).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } } } diff --git a/cli/src/test/java/bisq/cli/table/GetTradeCliOutputDiffTest.java b/cli/src/test/java/bisq/cli/table/GetTradeCliOutputDiffTest.java index 8516033ee67..25c6ceed5a4 100644 --- a/cli/src/test/java/bisq/cli/table/GetTradeCliOutputDiffTest.java +++ b/cli/src/test/java/bisq/cli/table/GetTradeCliOutputDiffTest.java @@ -9,7 +9,6 @@ import bisq.cli.AbstractCliTest; import bisq.cli.GrpcClient; -import bisq.cli.TradeFormat; import bisq.cli.table.builder.TableBuilder; @SuppressWarnings("unused") @@ -43,10 +42,12 @@ private void getBobsTrade() { private void getTrade(GrpcClient client) { var trade = client.getTrade(tradeId); - var oldTbl = TradeFormat.format(trade); + // TradeFormat class had been deprecated, then deleted on 17-Feb-2022, but these + // diff tests can be useful for testing changes to the current tbl formatting api. + // var oldTbl = TradeFormat.format(trade); var newTbl = new TableBuilder(TRADE_DETAIL_TBL, trade).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } } diff --git a/cli/src/test/java/bisq/cli/table/GetTransactionCliOutputDiffTest.java b/cli/src/test/java/bisq/cli/table/GetTransactionCliOutputDiffTest.java index 13fb639b6ed..d72749cd245 100644 --- a/cli/src/test/java/bisq/cli/table/GetTransactionCliOutputDiffTest.java +++ b/cli/src/test/java/bisq/cli/table/GetTransactionCliOutputDiffTest.java @@ -7,7 +7,6 @@ import bisq.cli.AbstractCliTest; -import bisq.cli.TransactionFormat; import bisq.cli.table.builder.TableBuilder; @SuppressWarnings("unused") @@ -31,11 +30,12 @@ public GetTransactionCliOutputDiffTest(String transactionId) { private void getTransaction() { var tx = aliceClient.getTransaction(transactionId); - var oldTbl = TransactionFormat.format(tx); + // TransactionFormat class had been deprecated, then deleted on 17-Feb-2022, but + // these diff tests can be useful for testing changes to the current tbl formatting api. + // var oldTbl = TransactionFormat.format(tx); var newTbl = new TableBuilder(TRANSACTION_TBL, tx).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - // Should show 1 (OK) diff due to new 'Is Confirmed' column being left justified (fixed). - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } } diff --git a/cli/src/test/java/bisq/cli/table/PaymentAccountsCliOutputDiffTest.java b/cli/src/test/java/bisq/cli/table/PaymentAccountsCliOutputDiffTest.java index bf1ca88a1c4..30dda73d086 100644 --- a/cli/src/test/java/bisq/cli/table/PaymentAccountsCliOutputDiffTest.java +++ b/cli/src/test/java/bisq/cli/table/PaymentAccountsCliOutputDiffTest.java @@ -2,7 +2,6 @@ import lombok.extern.slf4j.Slf4j; -import static bisq.cli.TableFormat.formatPaymentAcctTbl; import static bisq.cli.table.builder.TableType.PAYMENT_ACCOUNT_TBL; @@ -26,11 +25,13 @@ public PaymentAccountsCliOutputDiffTest() { private void getPaymentAccounts() { var paymentAccounts = aliceClient.getPaymentAccounts(); if (paymentAccounts.size() > 0) { - var oldTbl = formatPaymentAcctTbl(paymentAccounts); + // The formatPaymentAcctTbl method had been deprecated, then deleted on 17-Feb-2022, + // but these diff tests can be useful for testing changes to the current tbl formatting api. + // var oldTbl = formatPaymentAcctTbl(paymentAccounts); var newTbl = new TableBuilder(PAYMENT_ACCOUNT_TBL, paymentAccounts).build().toString(); - printOldTbl(oldTbl); + // printOldTbl(oldTbl); printNewTbl(newTbl); - checkDiffsIgnoreWhitespace(oldTbl, newTbl); + // checkDiffsIgnoreWhitespace(oldTbl, newTbl); } else { log.warn("no payment accounts found"); } From 461edff6311b9d3ee74f4a83098a39deb8a7a709 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 17:27:15 -0300 Subject: [PATCH 05/17] Change OfferInfo proto's 'price' field type to string Much less ambiguous field value at cost of breaking backward compat in API. --- .../main/java/bisq/core/api/model/OfferInfo.java | 8 ++++++-- .../core/api/model/builder/OfferInfoBuilder.java | 4 ++-- proto/src/main/proto/grpc.proto | 13 +++++-------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/bisq/core/api/model/OfferInfo.java b/core/src/main/java/bisq/core/api/model/OfferInfo.java index 7e4c8c49b13..53e2f6537d8 100644 --- a/core/src/main/java/bisq/core/api/model/OfferInfo.java +++ b/core/src/main/java/bisq/core/api/model/OfferInfo.java @@ -28,6 +28,7 @@ import lombok.Getter; import lombok.ToString; +import static bisq.core.util.PriceUtil.reformatMarketPrice; import static java.util.Objects.requireNonNull; @EqualsAndHashCode @@ -41,7 +42,7 @@ public class OfferInfo implements Payload { private final String id; private final String direction; - private final long price; + private final String price; private final boolean useMarketBasedPrice; private final double marketPriceMargin; private final long amount; @@ -136,10 +137,13 @@ public static OfferInfo toMyOfferInfo(OpenOffer openOffer) { } private static OfferInfoBuilder getBuilder(Offer offer, boolean isMyOffer) { + var preciseOfferPrice = reformatMarketPrice( + requireNonNull(offer.getPrice()).toPlainString(), + offer.getCurrencyCode()); return new OfferInfoBuilder() .withId(offer.getId()) .withDirection(offer.getDirection().name()) - .withPrice(requireNonNull(offer.getPrice()).getValue()) + .withPrice(preciseOfferPrice) .withUseMarketBasedPrice(offer.isUseMarketBasedPrice()) .withMarketPriceMargin(offer.getMarketPriceMargin()) .withAmount(offer.getAmount().value) diff --git a/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java b/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java index 3773b465f72..556ef9b2a48 100644 --- a/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java +++ b/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java @@ -32,7 +32,7 @@ public final class OfferInfoBuilder { private String id; private String direction; - private long price; + private String price; private boolean useMarketBasedPrice; private double marketPriceMargin; private long amount; @@ -72,7 +72,7 @@ public OfferInfoBuilder withDirection(String direction) { return this; } - public OfferInfoBuilder withPrice(long price) { + public OfferInfoBuilder withPrice(String price) { this.price = price; return this; } diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index f39ce446bb5..51a2229445b 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -242,8 +242,8 @@ message EditOfferRequest { // 0 = disable // 1 = enable sint32 enable = 6; - // The EditType determines and constricts what offer details can - // be modified by the request, simplifying param validation. + // The EditType determines and constricts what offer details can be modified by the request, simplifying param + // validation. (The CLI need to infer this detail from 'editoffer' command options, other clients do not.) enum EditType { // Edit only the offer's activation state (enabled or disabled). ACTIVATION_STATE_ONLY = 0; @@ -286,12 +286,9 @@ message OfferInfo { string id = 1; // The offer's BUY (BTC) or SELL (BTC) direction. string direction = 2; - // For fiat offers: a long representing the BTC price of the offer to 4 decimal places. - // A USD fiat price of 45000.4321 USD is represented as 450004321. - // For altcoin offers: a long representing the BTC price of the offer in satoshis. - // An altcoin price of five hundred thousand satoshis is represented as 500000. - // TODO: Change to string type. - uint64 price = 3; + // For fiat offers: the fiat price for 1 BTC to 4 decimal places, e.g., 45000 EUR is "45000.0000". + // For altcoin offers: the altcoin price for 1 BTC to 8 decimal places, e.g., 0.5 BTC is "0.00005000". + string price = 3; // Whether the offer price is fixed, or market price margin based. bool useMarketBasedPrice = 4; // The offer's market price margin above or below the current market BTC price, represented as a decimal. From 3405dbf5c3d53972ecac312403e0bb6bc1968846 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 17:57:45 -0300 Subject: [PATCH 06/17] Adjust cli module to OfferInfo.price field change to string type --- cli/src/main/java/bisq/cli/CurrencyFormat.java | 1 + .../bisq/cli/request/OffersServiceRequest.java | 15 +++------------ .../bisq/cli/table/builder/OfferTableBuilder.java | 14 +++++++------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/cli/src/main/java/bisq/cli/CurrencyFormat.java b/cli/src/main/java/bisq/cli/CurrencyFormat.java index a9d87146199..9f8df8fe88f 100644 --- a/cli/src/main/java/bisq/cli/CurrencyFormat.java +++ b/cli/src/main/java/bisq/cli/CurrencyFormat.java @@ -123,6 +123,7 @@ public static String formatInternalFiatPrice(double price) { return FRIENDLY_NUMBER_FORMAT.format(price); } + // TODO Deprecate after triggerPrice field type is changed to string. public static String formatPrice(long price) { FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(4); FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(4); diff --git a/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java b/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java index 7214d8bc0f8..20b9dc2c024 100644 --- a/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java +++ b/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java @@ -29,11 +29,8 @@ import bisq.proto.grpc.GetOffersRequest; import bisq.proto.grpc.OfferInfo; -import java.math.BigDecimal; - import java.util.ArrayList; import java.util.List; -import java.util.function.Function; import static bisq.cli.CryptoCurrencyUtil.apiDoesSupportCryptoCurrency; import static bisq.proto.grpc.EditOfferRequest.EditType.ACTIVATION_STATE_ONLY; @@ -52,12 +49,6 @@ public class OffersServiceRequest { - private final Function scaledPriceStringRequestFormat = (price) -> { - BigDecimal factor = new BigDecimal(10).pow(4); - //noinspection BigDecimalMethodWithoutRoundingCalled - return new BigDecimal(price).divide(factor).toPlainString(); - }; - private final GrpcStubs grpcStubs; public OffersServiceRequest(GrpcStubs grpcStubs) { @@ -159,11 +150,11 @@ public OfferInfo createOffer(String direction, public void editOfferActivationState(String offerId, int enable) { var offer = getMyOffer(offerId); - var scaledPriceString = offer.getUseMarketBasedPrice() + var offerPrice = offer.getUseMarketBasedPrice() ? "0.00" - : scaledPriceStringRequestFormat.apply(offer.getPrice()); + : offer.getPrice(); editOffer(offerId, - scaledPriceString, + offerPrice, offer.getUseMarketBasedPrice(), offer.getMarketPriceMargin(), offer.getTriggerPrice(), diff --git a/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java b/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java index 08d19c09106..e9ddc14e18d 100644 --- a/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java +++ b/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java @@ -80,7 +80,7 @@ public Table build() { public Table buildFiatOfferTable(List offers) { @Nullable Column colEnabled = enabledColumn.get(); // Not boolean: YES, NO, or PENDING - Column colFiatPrice = new FiatColumn(format(COL_HEADER_DETAILED_PRICE, fiatTradeCurrency.get())); + Column colFiatPrice = new StringColumn(format(COL_HEADER_DETAILED_PRICE, fiatTradeCurrency.get()), RIGHT); Column colFiatVolume = new FiatColumn(format("Temp Volume (%s)", fiatTradeCurrency.get()), NONE, VOLUME); Column colMinFiatVolume = new FiatColumn(format("Temp Min Volume (%s)", fiatTradeCurrency.get()), NONE, VOLUME); @Nullable @@ -121,7 +121,7 @@ public Table buildFiatOfferTable(List offers) { if (isShowingMyOffers.get()) { return new Table(colEnabled.asStringColumn(), colDirection, - colFiatPrice.asStringColumn(), + colFiatPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colTriggerPrice.asStringColumn(), @@ -130,7 +130,7 @@ public Table buildFiatOfferTable(List offers) { colOfferId); } else { return new Table(colDirection, - colFiatPrice.asStringColumn(), + colFiatPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colPaymentMethod, @@ -143,7 +143,7 @@ public Table buildFiatOfferTable(List offers) { public Table buildCryptoCurrencyOfferTable(List offers) { @Nullable Column colEnabled = enabledColumn.get(); // Not boolean: YES, NO, or PENDING - Column colBtcPrice = new SatoshiColumn(format(COL_HEADER_DETAILED_PRICE_OF_ALTCOIN, altcoinTradeCurrency.get())); + Column colBtcPrice = new StringColumn(format(COL_HEADER_DETAILED_PRICE_OF_ALTCOIN, altcoinTradeCurrency.get()), RIGHT); Column colBtcVolume = new AltcoinColumn(format("Temp Volume (%s)", altcoinTradeCurrency.get()), NONE, ALTCOIN_OFFER_VOLUME); @@ -189,7 +189,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { if (isShowingBsqOffers.get()) { return new Table(colEnabled.asStringColumn(), colDirection, - colBtcPrice.asStringColumn(), + colBtcPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colPaymentMethod, @@ -198,7 +198,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { } else { return new Table(colEnabled.asStringColumn(), colDirection, - colBtcPrice.asStringColumn(), + colBtcPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colTriggerPrice.asStringColumn(), @@ -208,7 +208,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { } } else { return new Table(colDirection, - colBtcPrice.asStringColumn(), + colBtcPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colPaymentMethod, From 89267e5851bb1c7ab27a21a7d6fb3838b0889240 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 18:11:46 -0300 Subject: [PATCH 07/17] Fix typo in comment --- proto/src/main/proto/grpc.proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 51a2229445b..5088dce390c 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -287,7 +287,7 @@ message OfferInfo { // The offer's BUY (BTC) or SELL (BTC) direction. string direction = 2; // For fiat offers: the fiat price for 1 BTC to 4 decimal places, e.g., 45000 EUR is "45000.0000". - // For altcoin offers: the altcoin price for 1 BTC to 8 decimal places, e.g., 0.5 BTC is "0.00005000". + // For altcoin offers: the altcoin price for 1 BTC to 8 decimal places, e.g., 0.00005 BTC is "0.00005000". string price = 3; // Whether the offer price is fixed, or market price margin based. bool useMarketBasedPrice = 4; From 1d70b1bb5f5ae6cf6b2ca5dd4b303ed3a15a93a6 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 18:18:54 -0300 Subject: [PATCH 08/17] Adjust apitest cases to OfferInfo.price proto field type to string --- .../method/offer/AbstractOfferTest.java | 22 ++-- .../method/offer/BsqSwapOfferTest.java | 2 +- .../method/offer/CreateBSQOffersTest.java | 16 +-- .../offer/CreateOfferUsingFixedPriceTest.java | 12 +- ...CreateOfferUsingMarketPriceMarginTest.java | 17 +-- .../method/offer/CreateXMROffersTest.java | 8 +- .../apitest/method/offer/EditOfferTest.java | 106 +++++++++--------- .../method/trade/BsqSwapBuyBtcTradeTest.java | 2 +- .../method/trade/BsqSwapSellBtcTradeTest.java | 2 +- .../LongRunningOfferDeactivationTest.java | 4 +- 10 files changed, 88 insertions(+), 103 deletions(-) diff --git a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java index 57495bb696a..4b64cd5308f 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java @@ -24,6 +24,7 @@ import protobuf.PaymentAccount; import java.math.BigDecimal; +import java.math.MathContext; import java.util.ArrayList; import java.util.List; @@ -100,13 +101,6 @@ public static void setUp() { return price.multiply(factor).longValue(); }; - // Price value of altcoin offer returned from server will be scaled up by 10^8. - protected final Function scaledUpAltcoinOfferPrice = (altcoinPriceAsString) -> { - BigDecimal factor = new BigDecimal(10).pow(8); - BigDecimal priceAsBigDecimal = new BigDecimal(altcoinPriceAsString); - return priceAsBigDecimal.multiply(factor).longValue(); - }; - protected final BiFunction calcFiatTriggerPriceAsLong = (base, delta) -> { var priceAsDouble = new BigDecimal(base).add(new BigDecimal(delta)).doubleValue(); return Double.valueOf(exactMultiply(priceAsDouble, 10_000)).longValue(); @@ -117,18 +111,20 @@ public static void setUp() { return Double.valueOf(exactMultiply(priceAsDouble, 100_000_000)).longValue(); }; - protected final BiFunction calcPriceAsString = (base, delta) -> { - var priceAsBigDecimal = new BigDecimal(Double.toString(base)) - .add(new BigDecimal(Double.toString(delta))); - return priceAsBigDecimal.toPlainString(); - }; - protected final Function toOfferTable = (offer) -> new TableBuilder(OFFER_TBL, offer).build().toString(); protected final Function, String> toOffersTable = (offers) -> new TableBuilder(OFFER_TBL, offers).build().toString(); + protected String calcPriceAsString(double base, double delta, int precision) { + var mathContext = new MathContext(precision); + var priceAsBigDecimal = new BigDecimal(Double.toString(base), mathContext) + .add(new BigDecimal(Double.toString(delta), mathContext)) + .round(mathContext); + return String.format("%." + precision + "f", priceAsBigDecimal.doubleValue()); + } + protected OfferInfo getAvailableBsqSwapOffer(GrpcClient client, OfferDirection direction, boolean checkForLoggedExceptions) { diff --git a/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java index c506794201e..60e96ca3dea 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/BsqSwapOfferTest.java @@ -117,7 +117,7 @@ private void createBsqSwapOffer() { var newOfferId = bsqSwapOffer.getId(); assertNotEquals("", newOfferId); assertEquals(BUY.name(), bsqSwapOffer.getDirection()); - assertEquals(5_000, bsqSwapOffer.getPrice()); + assertEquals("0.00005000", bsqSwapOffer.getPrice()); assertEquals(1_000_000L, bsqSwapOffer.getAmount()); assertEquals(1_000_000L, bsqSwapOffer.getMinAmount()); assertEquals(BSQ, bsqSwapOffer.getBaseCurrencyCode()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java index 43f87fd1568..57b318e68ed 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java @@ -74,7 +74,7 @@ public void testCreateBuy1BTCFor20KBSQOffer() { assertNotEquals("", newOfferId); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); @@ -91,7 +91,7 @@ public void testCreateBuy1BTCFor20KBSQOffer() { assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); @@ -121,7 +121,7 @@ public void testCreateSell1BTCFor20KBSQOffer() { assertNotEquals("", newOfferId); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); @@ -138,7 +138,7 @@ public void testCreateSell1BTCFor20KBSQOffer() { assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); @@ -168,7 +168,7 @@ public void testCreateBuyBTCWith1To2KBSQOffer() { assertNotEquals("", newOfferId); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(10_000_000L, newOffer.getAmount()); assertEquals(5_000_000L, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); @@ -185,7 +185,7 @@ public void testCreateBuyBTCWith1To2KBSQOffer() { assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(10_000_000L, newOffer.getAmount()); assertEquals(5_000_000L, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); @@ -215,7 +215,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() { assertNotEquals("", newOfferId); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(50_000_000L, newOffer.getAmount()); assertEquals(25_000_000L, newOffer.getMinAmount()); assertEquals(7_500_000, newOffer.getBuyerSecurityDeposit()); @@ -232,7 +232,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() { assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(5_000, newOffer.getPrice()); + assertEquals("0.00005000", newOffer.getPrice()); assertEquals(50_000_000L, newOffer.getAmount()); assertEquals(25_000_000L, newOffer.getMinAmount()); assertEquals(7_500_000, newOffer.getBuyerSecurityDeposit()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java index 7ec7d98d1d4..fb921a2cbdd 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java @@ -66,7 +66,7 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { assertNotEquals("", newOfferId); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(360_000_000, newOffer.getPrice()); + assertEquals("36000.0000", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); @@ -81,7 +81,7 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(360_000_000, newOffer.getPrice()); + assertEquals("36000.0000", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); @@ -111,7 +111,7 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { assertNotEquals("", newOfferId); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(300_001_234, newOffer.getPrice()); + assertEquals("30000.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); @@ -126,7 +126,7 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(300_001_234, newOffer.getPrice()); + assertEquals("30000.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); @@ -156,7 +156,7 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { assertNotEquals("", newOfferId); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(295_001_234, newOffer.getPrice()); + assertEquals("29500.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(5_000_000, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); @@ -171,7 +171,7 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(295_001_234, newOffer.getPrice()); + assertEquals("29500.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(5_000_000, newOffer.getMinAmount()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java index cce443206a3..a4f7f23e993 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java @@ -17,14 +17,11 @@ package bisq.apitest.method.offer; -import bisq.core.monetary.Altcoin; import bisq.core.monetary.Price; import bisq.core.payment.PaymentAccount; import bisq.proto.grpc.OfferInfo; -import org.bitcoinj.utils.Fiat; - import java.text.DecimalFormat; import java.math.BigDecimal; @@ -43,7 +40,6 @@ import static bisq.common.util.MathUtils.scaleDownByPowerOf10; import static bisq.common.util.MathUtils.scaleUpByPowerOf10; import static bisq.core.btc.wallet.Restrictions.getDefaultBuyerSecurityDepositAsPercent; -import static bisq.core.locale.CurrencyUtil.isCryptoCurrency; import static java.lang.Math.abs; import static java.lang.String.format; import static java.math.RoundingMode.HALF_UP; @@ -287,17 +283,17 @@ private void assertCalculatedPriceIsCorrect(OfferInfo offer, double priceMarginP assertTrue(() -> { String counterCurrencyCode = offer.getCounterCurrencyCode(); double mktPrice = aliceClient.getBtcPrice(counterCurrencyCode); - double scaledOfferPrice = getScaledOfferPrice(offer.getPrice(), counterCurrencyCode); + double priceAsDouble = Double.parseDouble(offer.getPrice()); double expectedDiffPct = scaleDownByPowerOf10(priceMarginPctInput, 2); double actualDiffPct = offer.getDirection().equals(BUY.name()) - ? getPercentageDifference(scaledOfferPrice, mktPrice) - : getPercentageDifference(mktPrice, scaledOfferPrice); + ? getPercentageDifference(priceAsDouble, mktPrice) + : getPercentageDifference(mktPrice, priceAsDouble); double pctDiffDelta = abs(expectedDiffPct) - abs(actualDiffPct); return isCalculatedPriceWithinErrorTolerance(pctDiffDelta, expectedDiffPct, actualDiffPct, mktPrice, - scaledOfferPrice, + priceAsDouble, offer); }); } @@ -308,11 +304,6 @@ private double getPercentageDifference(double price1, double price2) { .doubleValue(); } - private double getScaledOfferPrice(double offerPrice, String currencyCode) { - int precision = isCryptoCurrency(currencyCode) ? Altcoin.SMALLEST_UNIT_EXPONENT : Fiat.SMALLEST_UNIT_EXPONENT; - return scaleDownByPowerOf10(offerPrice, precision); - } - private boolean isCalculatedPriceWithinErrorTolerance(double delta, double expectedDiffPct, double actualDiffPct, diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java index cf40632e8d9..b945238d7ea 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java @@ -77,7 +77,7 @@ public void testCreateFixedPriceBuy1BTCFor200KXMROffer() { assertNotEquals("", newOfferId); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(500_000L, newOffer.getPrice()); + assertEquals("0.00500000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(75_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); @@ -94,7 +94,7 @@ public void testCreateFixedPriceBuy1BTCFor200KXMROffer() { assertEquals(newOfferId, newOffer.getId()); assertEquals(BUY.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(500_000L, newOffer.getPrice()); + assertEquals("0.00500000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(75_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); @@ -124,7 +124,7 @@ public void testCreateFixedPriceSell1BTCFor200KXMROffer() { assertNotEquals("", newOfferId); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(500_000L, newOffer.getPrice()); + assertEquals("0.00500000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(50_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); @@ -141,7 +141,7 @@ public void testCreateFixedPriceSell1BTCFor200KXMROffer() { assertEquals(newOfferId, newOffer.getId()); assertEquals(SELL.name(), newOffer.getDirection()); assertFalse(newOffer.getUseMarketBasedPrice()); - assertEquals(500_000L, newOffer.getPrice()); + assertEquals("0.00500000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(50_000_000L, newOffer.getMinAmount()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java index 33944dece8d..b0401c6522b 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java @@ -67,7 +67,7 @@ public void testOfferDisableAndEnable() { NO_TRIGGER_PRICE); log.debug("Original EUR offer:\n{}", toOfferTable.apply(originalOffer)); assertFalse(originalOffer.getIsActivated()); // Not activated until prep is done. - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); assertTrue(originalOffer.getIsActivated()); // Disable offer @@ -98,7 +98,7 @@ public void testEditTriggerPrice() { 0.0, NO_TRIGGER_PRICE); log.debug("Original EUR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); assertEquals(0 /*no trigger price*/, originalOffer.getTriggerPrice()); @@ -127,7 +127,7 @@ public void testSetTriggerPriceToNegativeValueShouldThrowException() { 0.0, NO_TRIGGER_PRICE); log.debug("Original EUR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. // Edit the offer's trigger price, set to -1, check error. Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOfferTriggerPrice(originalOffer.getId(), -1L)); @@ -148,7 +148,7 @@ public void testEditMktPriceMargin() { originalMktPriceMargin, NO_TRIGGER_PRICE); log.debug("Original USD offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. assertEquals(scaledDownMktPriceMargin.apply(originalMktPriceMargin), originalOffer.getMarketPriceMargin()); // Edit the offer's price margin, nothing else. var newMktPriceMargin = new BigDecimal("0.5").doubleValue(); @@ -166,22 +166,21 @@ public void testEditMktPriceMargin() { public void testEditFixedPrice() { PaymentAccount paymentAcct = getOrCreatePaymentAccount("RU"); double mktPriceAsDouble = aliceClient.getBtcPrice(RUBLE); - String fixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 200_000.0000); + String fixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 200_000.0000, 4); var originalOffer = createFixedPricedOfferForEdit(BUY.name(), RUBLE, paymentAcct.getId(), fixedPriceAsString); log.debug("Original RUB offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. // Edit the offer's fixed price, nothing else. - String editedFixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 100_000.0000); + String editedFixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 100_000.0000, 4); aliceClient.editOfferFixedPrice(originalOffer.getId(), editedFixedPriceAsString); // Wait for edited offer to be removed from offer-book, edited, and re-published. genBtcBlocksThenWait(1, 2_500); OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited RUB offer:\n{}", toOfferTable.apply(editedOffer)); - var expectedNewFixedPrice = scaledUpFiatOfferPrice.apply(new BigDecimal(editedFixedPriceAsString)); - assertEquals(expectedNewFixedPrice, editedOffer.getPrice()); + assertEquals(editedFixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); doSanityCheck(originalOffer, editedOffer); @@ -192,15 +191,15 @@ public void testEditFixedPrice() { public void testEditFixedPriceAndDeactivation() { PaymentAccount paymentAcct = getOrCreatePaymentAccount("RU"); double mktPriceAsDouble = aliceClient.getBtcPrice(RUBLE); - String fixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 200_000.0000); + String fixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 200_000.0000, 4); var originalOffer = createFixedPricedOfferForEdit(BUY.name(), RUBLE, paymentAcct.getId(), fixedPriceAsString); log.debug("Original RUB offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. // Edit the offer's fixed price and deactivate it. - String editedFixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 100_000.0000); + String editedFixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 100_000.0000, 4); aliceClient.editOffer(originalOffer.getId(), editedFixedPriceAsString, originalOffer.getUseMarketBasedPrice(), @@ -212,8 +211,7 @@ public void testEditFixedPriceAndDeactivation() { genBtcBlocksThenWait(1, 2_500); OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited RUB offer:\n{}", toOfferTable.apply(editedOffer)); - var expectedNewFixedPrice = scaledUpFiatOfferPrice.apply(new BigDecimal(editedFixedPriceAsString)); - assertEquals(expectedNewFixedPrice, editedOffer.getPrice()); + assertEquals(editedFixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getIsActivated()); assertFalse(editedOffer.getUseMarketBasedPrice()); @@ -232,7 +230,7 @@ public void testEditMktPriceMarginAndDeactivation() { originalMktPriceMargin, 0); log.debug("Original USD offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); assertEquals(scaledDownMktPriceMargin.apply(originalMktPriceMargin), originalOffer.getMarketPriceMargin()); @@ -270,7 +268,7 @@ public void testEditMktPriceMarginAndTriggerPriceAndDeactivation() { originalMktPriceMargin, originalTriggerPriceAsLong); log.debug("Original USD offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); assertEquals(scaledDownMktPriceMargin.apply(originalMktPriceMargin), originalOffer.getMarketPriceMargin()); assertEquals(originalTriggerPriceAsLong, originalOffer.getTriggerPrice()); @@ -307,7 +305,7 @@ public void testEditingFixedPriceInMktPriceMarginBasedOfferShouldThrowException( originalMktPriceMargin, NO_TRIGGER_PRICE); log.debug("Original USD offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. // Try to edit both the fixed price and mkt price margin. var newMktPriceMargin = new BigDecimal("0.25").doubleValue(); var newFixedPrice = "50000.0000"; @@ -332,13 +330,13 @@ public void testEditingFixedPriceInMktPriceMarginBasedOfferShouldThrowException( public void testEditingTriggerPriceInFixedPriceOfferShouldThrowException() { PaymentAccount paymentAcct = getOrCreatePaymentAccount("RU"); double mktPriceAsDouble = aliceClient.getBtcPrice(RUBLE); - String fixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 200_000.0000); + String fixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 200_000.0000, 4); var originalOffer = createFixedPricedOfferForEdit(BUY.name(), RUBLE, paymentAcct.getId(), fixedPriceAsString); log.debug("Original RUB offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. long newTriggerPrice = 1000000L; Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOfferTriggerPrice(originalOffer.getId(), newTriggerPrice)); @@ -354,13 +352,13 @@ public void testEditingTriggerPriceInFixedPriceOfferShouldThrowException() { public void testChangeFixedPriceOfferToPriceMarginBasedOfferWithTriggerPrice() { PaymentAccount paymentAcct = getOrCreatePaymentAccount("MX"); double mktPriceAsDouble = aliceClient.getBtcPrice("MXN"); - String fixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 0.00); + String fixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 0.00, 4); var originalOffer = createFixedPricedOfferForEdit(BUY.name(), "MXN", paymentAcct.getId(), fixedPriceAsString); log.debug("Original MXN offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. // Change the offer to mkt price based and set a trigger price. var newMktPriceMargin = new BigDecimal("0.05").doubleValue(); @@ -399,9 +397,9 @@ public void testChangePriceMarginBasedOfferToFixedPriceOfferAndDeactivateIt() { originalMktPriceMargin, originalTriggerPriceAsLong); log.debug("Original GBP offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. - String fixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 0.00); + String fixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 0.00, 4); aliceClient.editOffer(originalOffer.getId(), fixedPriceAsString, false, @@ -413,7 +411,7 @@ public void testChangePriceMarginBasedOfferToFixedPriceOfferAndDeactivateIt() { genBtcBlocksThenWait(1, 2_500); OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited GBP offer:\n{}", toOfferTable.apply(editedOffer)); - assertEquals(scaledUpFiatOfferPrice.apply(new BigDecimal(fixedPriceAsString)), editedOffer.getPrice()); + assertEquals(fixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); assertEquals(0, editedOffer.getTriggerPrice()); @@ -432,7 +430,7 @@ public void testChangeFixedPricedBsqOfferToPriceMarginBasedOfferShouldThrowExcep alicesLegacyBsqAcct.getId(), BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOffer(originalOffer.getId(), "0.00", @@ -459,7 +457,7 @@ public void testEditTriggerPriceOnFixedPriceBsqOfferShouldThrowException() { alicesLegacyBsqAcct.getId(), BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. var newTriggerPriceAsLong = calcFiatTriggerPriceAsLong.apply(0.00005, 0.00); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOffer(originalOffer.getId(), @@ -488,7 +486,7 @@ public void testEditFixedPriceOnBsqOffer() { alicesLegacyBsqAcct.getId(), BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. String newFixedPriceAsString = "0.00003111"; aliceClient.editOffer(originalOffer.getId(), newFixedPriceAsString, @@ -501,7 +499,7 @@ public void testEditFixedPriceOnBsqOffer() { genBtcBlocksThenWait(1, 2_500); OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited BSQ offer:\n{}", toOfferTable.apply(editedOffer)); - assertEquals(scaledUpAltcoinOfferPrice.apply(newFixedPriceAsString), editedOffer.getPrice()); + assertEquals(newFixedPriceAsString, editedOffer.getPrice()); assertTrue(editedOffer.getIsActivated()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); @@ -511,7 +509,7 @@ public void testEditFixedPriceOnBsqOffer() { @Test @Order(16) public void testDisableBsqOffer() { - String fixedPriceAsString = "0.00005"; // FIXED PRICE IN BTC (satoshis) FOR 1 BSQ + String fixedPriceAsString = "0.00005000"; var originalOffer = aliceClient.createFixedPricedOffer(BUY.name(), BSQ, 100_000_000L, @@ -521,7 +519,7 @@ public void testDisableBsqOffer() { alicesLegacyBsqAcct.getId(), BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. aliceClient.editOffer(originalOffer.getId(), fixedPriceAsString, false, @@ -534,7 +532,7 @@ public void testDisableBsqOffer() { OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited BSQ offer:\n{}", toOfferTable.apply(editedOffer)); assertFalse(editedOffer.getIsActivated()); - assertEquals(scaledUpAltcoinOfferPrice.apply(fixedPriceAsString), editedOffer.getPrice()); + assertEquals(fixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); assertEquals(0, editedOffer.getTriggerPrice()); @@ -543,7 +541,7 @@ public void testDisableBsqOffer() { @Test @Order(17) public void testEditFixedPriceAndDisableBsqOffer() { - String fixedPriceAsString = "0.00005"; // FIXED PRICE IN BTC (satoshis) FOR 1 BSQ + String fixedPriceAsString = "0.00005000"; var originalOffer = aliceClient.createFixedPricedOffer(BUY.name(), BSQ, 100_000_000L, @@ -553,8 +551,8 @@ public void testEditFixedPriceAndDisableBsqOffer() { alicesLegacyBsqAcct.getId(), BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. - String newFixedPriceAsString = "0.000045"; + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. + String newFixedPriceAsString = "0.00004500"; aliceClient.editOffer(originalOffer.getId(), newFixedPriceAsString, false, @@ -567,7 +565,7 @@ public void testEditFixedPriceAndDisableBsqOffer() { OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited BSQ offer:\n{}", toOfferTable.apply(editedOffer)); assertFalse(editedOffer.getIsActivated()); - assertEquals(scaledUpAltcoinOfferPrice.apply(newFixedPriceAsString), editedOffer.getPrice()); + assertEquals(newFixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); assertEquals(0, editedOffer.getTriggerPrice()); @@ -587,12 +585,12 @@ public void testChangePriceMarginBasedXmrOfferWithTriggerPriceToFixedPricedAndDe 0.0, triggerPriceAsLong); log.debug("Pending XMR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); - String newFixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, -0.001); + String newFixedPriceAsString = calcPriceAsString(mktPriceAsDouble, -0.001, 8); aliceClient.editOffer(originalOffer.getId(), newFixedPriceAsString, false, @@ -604,7 +602,7 @@ public void testChangePriceMarginBasedXmrOfferWithTriggerPriceToFixedPricedAndDe genBtcBlocksThenWait(1, 2500); OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited XMR offer:\n{}", toOfferTable.apply(editedOffer)); - assertEquals(scaledUpAltcoinOfferPrice.apply(newFixedPriceAsString), editedOffer.getPrice()); + assertEquals(newFixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); assertEquals(0, editedOffer.getTriggerPrice()); @@ -624,7 +622,7 @@ public void testEditTriggerPriceOnPriceMarginBasedXmrOffer() { mktPriceMargin, NO_TRIGGER_PRICE); log.debug("Pending XMR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); log.info("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); @@ -655,7 +653,7 @@ public void testEditTriggerPriceOnPriceMarginBasedXmrOffer() { public void testChangeFixedPricedXmrOfferToPriceMarginBasedOfferWithTriggerPrice() { createXmrPaymentAccounts(); double mktPriceAsDouble = aliceClient.getBtcPrice(XMR); - String fixedPriceAsString = calcPriceAsString.apply(mktPriceAsDouble, 0.00); + String fixedPriceAsString = calcPriceAsString(mktPriceAsDouble, 0.00, 8); OfferInfo originalOffer = aliceClient.createFixedPricedOffer(BUY.name(), XMR, 100_000_000L, @@ -665,7 +663,7 @@ public void testChangeFixedPricedXmrOfferToPriceMarginBasedOfferWithTriggerPrice alicesXmrAcct.getId(), BSQ); log.debug("Pending XMR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); @@ -706,7 +704,7 @@ public void testEditTriggerPriceOnFixedPriceXmrOfferShouldThrowException() { alicesXmrAcct.getId(), BSQ); log.debug("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. var newTriggerPriceAsLong = calcAltcoinTriggerPriceAsLong.apply(0.007, 0.001); Throwable exception = assertThrows(StatusRuntimeException.class, () -> @@ -737,8 +735,8 @@ public void testEditFixedPriceOnXmrOffer() { alicesXmrAcct.getId(), BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. - String newFixedPriceAsString = "0.009"; + genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. + String newFixedPriceAsString = "0.00900000"; aliceClient.editOffer(originalOffer.getId(), newFixedPriceAsString, false, @@ -750,7 +748,7 @@ public void testEditFixedPriceOnXmrOffer() { genBtcBlocksThenWait(1, 2500); OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited XMR offer:\n{}", toOfferTable.apply(editedOffer)); - assertEquals(scaledUpAltcoinOfferPrice.apply(newFixedPriceAsString), editedOffer.getPrice()); + assertEquals(newFixedPriceAsString, editedOffer.getPrice()); assertTrue(editedOffer.getIsActivated()); assertMarketBasedPriceFieldsAreIgnored(editedOffer); @@ -761,7 +759,7 @@ public void testEditFixedPriceOnXmrOffer() { @Order(23) public void testDisableXmrOffer() { createXmrPaymentAccounts(); - String fixedPriceAsString = "0.008"; // FIXED PRICE IN BTC (satoshis) FOR 1 BSQ + String fixedPriceAsString = "0.00800000"; final OfferInfo originalOffer = aliceClient.createFixedPricedOffer(BUY.name(), XMR, 100_000_000L, @@ -771,7 +769,7 @@ public void testDisableXmrOffer() { alicesXmrAcct.getId(), BSQ); log.debug("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. aliceClient.editOffer(originalOffer.getId(), fixedPriceAsString, false, @@ -784,7 +782,7 @@ public void testDisableXmrOffer() { OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited XMR offer:\n{}", toOfferTable.apply(editedOffer)); assertFalse(editedOffer.getIsActivated()); - assertEquals(scaledUpAltcoinOfferPrice.apply(fixedPriceAsString), editedOffer.getPrice()); + assertEquals(fixedPriceAsString, editedOffer.getPrice()); assertMarketBasedPriceFieldsAreIgnored(editedOffer); doSanityCheck(originalOffer, editedOffer); @@ -794,7 +792,7 @@ public void testDisableXmrOffer() { @Order(24) public void testEditFixedPriceAndDisableXmrOffer() { createXmrPaymentAccounts(); - String fixedPriceAsString = "0.004"; // FIXED PRICE IN BTC (satoshis) FOR 1 BSQ + String fixedPriceAsString = "0.004"; final OfferInfo originalOffer = aliceClient.createFixedPricedOffer(BUY.name(), XMR, 100_000_000L, @@ -804,8 +802,8 @@ public void testEditFixedPriceAndDisableXmrOffer() { alicesXmrAcct.getId(), BSQ); log.debug("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. - String newFixedPriceAsString = "0.000045"; + genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. + String newFixedPriceAsString = "0.00004500"; aliceClient.editOffer(originalOffer.getId(), newFixedPriceAsString, false, @@ -818,7 +816,7 @@ public void testEditFixedPriceAndDisableXmrOffer() { OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited XMR offer:\n{}", toOfferTable.apply(editedOffer)); assertFalse(editedOffer.getIsActivated()); - assertEquals(scaledUpAltcoinOfferPrice.apply(newFixedPriceAsString), editedOffer.getPrice()); + assertEquals(newFixedPriceAsString, editedOffer.getPrice()); assertMarketBasedPriceFieldsAreIgnored(editedOffer); doSanityCheck(originalOffer, editedOffer); @@ -837,14 +835,14 @@ public void testEditBsqSwapOfferShouldThrowException() { var newOfferId = originalOffer.getId(); assertNotEquals("", newOfferId); assertEquals(SELL.name(), originalOffer.getDirection()); - assertEquals(5_000, originalOffer.getPrice()); + assertEquals("0.00005000", originalOffer.getPrice()); assertEquals(1_250_000L, originalOffer.getAmount()); assertEquals(750_000L, originalOffer.getMinAmount()); assertEquals(BSQ, originalOffer.getBaseCurrencyCode()); assertEquals(BTC, originalOffer.getCounterCurrencyCode()); log.debug("Original BsqSwap offer:\n{}", toOfferTable.apply(originalOffer)); - genBtcBlocksThenWait(1, 2_500); // Wait for offer book entry. + genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. var newFixedPrice = "0.000055"; Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOffer(originalOffer.getId(), diff --git a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java index cfa330e7478..1072b21fc96 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapBuyBtcTradeTest.java @@ -89,7 +89,7 @@ public void testAliceCreateBsqSwapBuyBtcOffer() { var newOfferId = mySwapOffer.getId(); assertNotEquals("", newOfferId); assertEquals(OfferDirection.BUY.name(), mySwapOffer.getDirection()); - assertEquals(5_000, mySwapOffer.getPrice()); + assertEquals("0.00005000", mySwapOffer.getPrice()); assertEquals(1_000_000L, mySwapOffer.getAmount()); assertEquals(1_000_000L, mySwapOffer.getMinAmount()); assertEquals(BSQ, mySwapOffer.getBaseCurrencyCode()); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java index 80cd48ec1f0..d699428c844 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/BsqSwapSellBtcTradeTest.java @@ -87,7 +87,7 @@ public void testAliceCreateBsqSwapSellBtcOffer() { var newOfferId = mySwapOffer.getId(); assertNotEquals("", newOfferId); assertEquals(SELL.name(), mySwapOffer.getDirection()); - assertEquals(5_000, mySwapOffer.getPrice()); + assertEquals("0.00005000", mySwapOffer.getPrice()); assertEquals(1_000_000L, mySwapOffer.getAmount()); assertEquals(1_000_000L, mySwapOffer.getMinAmount()); assertEquals(BSQ, mySwapOffer.getBaseCurrencyCode()); diff --git a/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java b/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java index 61904bfad8b..7dee678d2c6 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java +++ b/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java @@ -72,7 +72,7 @@ public void testSellOfferAutoDisable(final TestInfo testInfo) { triggerPrice); log.info("SELL offer {} created with margin based price {}.", offer.getId(), - formatPrice(offer.getPrice())); + offer.getPrice()); genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. offer = aliceClient.getOffer(offer.getId()); // Offer has trigger price now. @@ -120,7 +120,7 @@ public void testBuyOfferAutoDisable(final TestInfo testInfo) { triggerPrice); log.info("BUY offer {} created with margin based price {}.", offer.getId(), - formatPrice(offer.getPrice())); + offer.getPrice()); genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. offer = aliceClient.getOffer(offer.getId()); // Offer has trigger price now. From 18888f4d7a6b8d78e378cb5fa3d146e4ddd7f218 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Thu, 17 Feb 2022 18:30:27 -0300 Subject: [PATCH 09/17] Fix 'unnecessary use of fully qualified name'. --- .../test/java/bisq/apitest/method/offer/AbstractOfferTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java index 4b64cd5308f..e014792565a 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java @@ -122,7 +122,7 @@ protected String calcPriceAsString(double base, double delta, int precision) { var priceAsBigDecimal = new BigDecimal(Double.toString(base), mathContext) .add(new BigDecimal(Double.toString(delta), mathContext)) .round(mathContext); - return String.format("%." + precision + "f", priceAsBigDecimal.doubleValue()); + return format("%." + precision + "f", priceAsBigDecimal.doubleValue()); } protected OfferInfo getAvailableBsqSwapOffer(GrpcClient client, From 62a0a1405d18a93275346b8220242e11824b5c17 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 11:23:41 -0300 Subject: [PATCH 10/17] Change existing `uint64 triggerPrice` field type in grpc.proto to `string triggerPrice`. --- proto/src/main/proto/grpc.proto | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 5088dce390c..87f6609f275 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -209,11 +209,10 @@ message CreateOfferRequest { // TODO: This parameter (where 0.## represents ##%) conflicts with marketPriceMargin (where #.## literally represents #.##%). // Backward compat breaking change to buyerSecurityDeposit is needed to make it consistent with marketPriceMargin (or vice-versa). double buyerSecurityDeposit = 8; - // For fiat, market price margin based offer, the current market BTC price at which the offer is automatically disabled. - // The parameter type is a long, representing the fiat price to 4 decimal places, but without the decimal. - // For example trigger price in EUR of 43749.3940 would be passed as 437493940. - // TODO: This should be a string type: "43749.3940", and converted to a long on the server. - uint64 triggerPrice = 9; + // A market price margin based offer's trigger price is the market BTC price at which the offer is automatically disabled. + // Disabled offers are never automatically enabled, they must be manually re-enabled. + // A zero value indicates trigger price is not set. Trigger price does not apply to fixed price offers. + string triggerPrice = 9; // The unique identifier of the payment account used to create the new offer, and send or receive trade payment. string paymentAccountId = 10; // The offer maker's trade fee currency: BTC or BSQ. @@ -234,8 +233,10 @@ message EditOfferRequest { bool useMarketBasedPrice = 3; // The offer's new market price margin as a percentage above or below the current market BTC price. double marketPriceMargin = 4; - // For market price margin based offer, the current market BTC price at which the offer is automatically disabled. - uint64 triggerPrice = 5; + // A market price margin based offer's trigger price is the market BTC price at which the offer is automatically disabled. + // Disabled offers are never automatically enabled, they must be manually re-enabled. + // A zero value indicates trigger price is not set. Trigger price does not apply to fixed price offers. + string triggerPrice = 5; // Whether the offer's activation state should be changed (disable or enable), or left alone. // Send a signed int, not a bool (with default=false). // -1 = do not change activation state @@ -311,10 +312,10 @@ message OfferInfo { uint64 minVolume = 9; // A long representing the BTC buyer's security deposit in satoshis. uint64 buyerSecurityDeposit = 10; - // A long representing a market price margin based offer's trigger price: the current market BTC price at - // which the offer is automatically disabled. For fiat offers, a trigger price of 40000.5000 is represented - // as 400005000. - uint64 triggerPrice = 11; + // A market price margin based offer's trigger price is the market BTC price at which the offer is automatically disabled. + // Disabled offers are never automatically enabled, they must be manually re-enabled. + // A zero value indicates trigger price is not set. Trigger price does not apply to fixed price offers. + string triggerPrice = 11; // Whether the offer maker paid the trading fee in BTC or not (BSQ). bool isCurrencyForMakerFeeBtc = 12; // The unique identifier of the payment account used to create the offer. From fafe416e856ace9214c548465d783932aa92156f Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 11:24:02 -0300 Subject: [PATCH 11/17] Adjust to `string triggerPrice` change in API core classes. --- core/src/main/java/bisq/core/api/CoreApi.java | 12 +++++------ .../java/bisq/core/api/CoreOffersService.java | 19 ++++++++++------- .../bisq/core/api/EditOfferValidator.java | 21 ++++++++++--------- .../java/bisq/core/api/model/OfferInfo.java | 16 +++++++++++--- .../api/model/builder/OfferInfoBuilder.java | 4 ++-- 5 files changed, 43 insertions(+), 29 deletions(-) diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java index 5740d47b88f..2587b51d60f 100644 --- a/core/src/main/java/bisq/core/api/CoreApi.java +++ b/core/src/main/java/bisq/core/api/CoreApi.java @@ -194,19 +194,19 @@ public void createAndPlaceBsqSwapOffer(String directionAsString, public void createAndPlaceOffer(String currencyCode, String directionAsString, - String priceAsString, + String price, boolean useMarketBasedPrice, double marketPriceMargin, long amountAsLong, long minAmountAsLong, double buyerSecurityDeposit, - long triggerPrice, + String triggerPrice, String paymentAccountId, String makerFeeCurrencyCode, Consumer resultHandler) { coreOffersService.createAndPlaceOffer(currencyCode, directionAsString, - priceAsString, + price, useMarketBasedPrice, marketPriceMargin, amountAsLong, @@ -219,14 +219,14 @@ public void createAndPlaceOffer(String currencyCode, } public void editOffer(String offerId, - String priceAsString, + String price, boolean useMarketBasedPrice, double marketPriceMargin, - long triggerPrice, + String triggerPrice, int enable, EditType editType) { coreOffersService.editOffer(offerId, - priceAsString, + price, useMarketBasedPrice, marketPriceMargin, triggerPrice, diff --git a/core/src/main/java/bisq/core/api/CoreOffersService.java b/core/src/main/java/bisq/core/api/CoreOffersService.java index f321ad17d0c..03764b7d1e5 100644 --- a/core/src/main/java/bisq/core/api/CoreOffersService.java +++ b/core/src/main/java/bisq/core/api/CoreOffersService.java @@ -66,6 +66,7 @@ import static bisq.core.offer.OpenOffer.State.AVAILABLE; import static bisq.core.offer.OpenOffer.State.DEACTIVATED; import static bisq.core.payment.PaymentAccountUtil.isPaymentAccountValidForOffer; +import static bisq.core.util.PriceUtil.getMarketPriceAsLong; import static bisq.proto.grpc.EditOfferRequest.EditType; import static bisq.proto.grpc.EditOfferRequest.EditType.FIXED_PRICE_AND_ACTIVATION_STATE; import static bisq.proto.grpc.EditOfferRequest.EditType.FIXED_PRICE_ONLY; @@ -276,7 +277,7 @@ void createAndPlaceOffer(String currencyCode, long amountAsLong, long minAmountAsLong, double buyerSecurityDeposit, - long triggerPrice, + String triggerPrice, String paymentAccountId, String makerFeeCurrencyCode, Consumer resultHandler) { @@ -321,15 +322,15 @@ void createAndPlaceOffer(String currencyCode, // Edit a placed offer. void editOffer(String offerId, - String editedPriceAsString, + String editedPrice, boolean editedUseMarketBasedPrice, double editedMarketPriceMargin, - long editedTriggerPrice, + String editedTriggerPrice, int editedEnable, EditType editType) { OpenOffer openOffer = getMyOpenOffer(offerId); var validator = new EditOfferValidator(openOffer, - editedPriceAsString, + editedPrice, editedUseMarketBasedPrice, editedMarketPriceMargin, editedTriggerPrice, @@ -346,7 +347,7 @@ void editOffer(String offerId, : editedEnable > 0 ? AVAILABLE : DEACTIVATED; OfferPayload editedPayload = getMergedOfferPayload(validator, openOffer, - editedPriceAsString, + editedPrice, editedMarketPriceMargin, editType); Offer editedOffer = new Offer(editedPayload); @@ -356,8 +357,9 @@ void editOffer(String offerId, openOfferManager.editOpenOfferStart(openOffer, () -> log.info("EditOpenOfferStart: offer {}", openOffer.getId()), log::error); + long triggerPriceAsLong = getMarketPriceAsLong(editedTriggerPrice, editedOffer.getCurrencyCode()); openOfferManager.editOpenOfferPublish(editedOffer, - editedTriggerPrice, + triggerPriceAsLong, newOfferState, () -> log.info("EditOpenOfferPublish: offer {}", openOffer.getId()), log::error); @@ -382,13 +384,14 @@ private void placeBsqSwapOffer(Offer offer, Runnable resultHandler) { private void placeOffer(Offer offer, double buyerSecurityDeposit, - long triggerPrice, + String triggerPrice, boolean useSavingsWallet, Consumer resultHandler) { + var triggerPriceAsLong = getMarketPriceAsLong(triggerPrice, offer.getCurrencyCode()); openOfferManager.placeOffer(offer, buyerSecurityDeposit, useSavingsWallet, - triggerPrice, + triggerPriceAsLong, resultHandler::accept, log::error); diff --git a/core/src/main/java/bisq/core/api/EditOfferValidator.java b/core/src/main/java/bisq/core/api/EditOfferValidator.java index 34515da5548..977b7a738e7 100644 --- a/core/src/main/java/bisq/core/api/EditOfferValidator.java +++ b/core/src/main/java/bisq/core/api/EditOfferValidator.java @@ -14,6 +14,7 @@ import static bisq.proto.grpc.EditOfferRequest.EditType.*; import static java.lang.String.format; +import static java.math.BigDecimal.ZERO; @Slf4j class EditOfferValidator { @@ -49,10 +50,10 @@ class EditOfferValidator { private final OpenOffer currentlyOpenOffer; - private final String newPriceAsString; + private final String newPrice; private final boolean newIsUseMarketBasedPrice; private final double newMarketPriceMargin; - private final long newTriggerPrice; + private final String newTriggerPrice; private final int newEnable; private final EditOfferRequest.EditType editType; @@ -60,14 +61,14 @@ class EditOfferValidator { private final boolean isZeroEditedTriggerPrice; EditOfferValidator(OpenOffer currentlyOpenOffer, - String newPriceAsString, + String newPrice, boolean newIsUseMarketBasedPrice, double newMarketPriceMargin, - long newTriggerPrice, + String newTriggerPrice, int newEnable, EditOfferRequest.EditType editType) { this.currentlyOpenOffer = currentlyOpenOffer; - this.newPriceAsString = newPriceAsString; + this.newPrice = newPrice; // The client cannot determine what offer.isUseMarketBasedPrice should be // when editType = ACTIVATION_STATE_ONLY. Override newIsUseMarketBasedPrice // param for the ACTIVATION_STATE_ONLY case. @@ -81,8 +82,8 @@ class EditOfferValidator { this.newEnable = newEnable; this.editType = editType; - this.isZeroEditedFixedPriceString = new BigDecimal(newPriceAsString).doubleValue() == 0; - this.isZeroEditedTriggerPrice = newTriggerPrice == 0; + this.isZeroEditedFixedPriceString = new BigDecimal(newPrice).doubleValue() == 0; + this.isZeroEditedTriggerPrice = new BigDecimal(newTriggerPrice).equals(ZERO); } EditOfferValidator validate() { @@ -123,7 +124,7 @@ public String toString() { return "EditOfferValidator{" + "\n" + " offer=" + offer.getId() + "\n" + ", offer.payloadBase.price=" + offer.getOfferPayloadBase().getPrice() + "\n" + - ", newPriceAsString=" + (isEditingPrice ? newPriceAsString : "N/A") + "\n" + + ", newPrice=" + (isEditingPrice ? newPrice : "N/A") + "\n" + ", offer.useMarketBasedPrice=" + offer.isUseMarketBasedPrice() + "\n" + ", newUseMarketBasedPrice=" + newIsUseMarketBasedPrice + "\n" + ", offer.marketPriceMargin=" + offer.getMarketPriceMargin() + "\n" + @@ -182,7 +183,7 @@ private void validateEditedMarketPriceMargin() { throw new IllegalStateException( format("programmer error: cannot set fixed price (%s)" + " in mkt price margin based offer with id '%s'", - newPriceAsString, + newPrice, currentlyOpenOffer.getId())); } @@ -195,7 +196,7 @@ private void validateEditedTriggerPrice() { + " in fixed price offer with id '%s'", currentlyOpenOffer.getId())); - if (newTriggerPrice < 0) + if (new BigDecimal(newTriggerPrice).compareTo(ZERO) < 0) throw new IllegalStateException( format("programmer error: cannot set trigger price to a negative value" + " in offer with id '%s'", diff --git a/core/src/main/java/bisq/core/api/model/OfferInfo.java b/core/src/main/java/bisq/core/api/model/OfferInfo.java index 53e2f6537d8..c3703d2ab42 100644 --- a/core/src/main/java/bisq/core/api/model/OfferInfo.java +++ b/core/src/main/java/bisq/core/api/model/OfferInfo.java @@ -18,12 +18,15 @@ package bisq.core.api.model; import bisq.core.api.model.builder.OfferInfoBuilder; +import bisq.core.monetary.Price; import bisq.core.offer.Offer; import bisq.core.offer.OpenOffer; import bisq.core.util.coin.CoinUtil; import bisq.common.Payload; +import java.util.Optional; + import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.ToString; @@ -54,7 +57,7 @@ public class OfferInfo implements Payload { private final String offerFeePaymentTxId; private final long buyerSecurityDeposit; private final long sellerSecurityDeposit; - private final long triggerPrice; + private final String triggerPrice; private final boolean isCurrencyForMakerFeeBtc; private final String paymentAccountId; private final String paymentMethodId; @@ -130,8 +133,15 @@ public static OfferInfo toMyPendingOfferInfo(Offer myNewOffer) { public static OfferInfo toMyOfferInfo(OpenOffer openOffer) { // An OpenOffer is always my offer. + var currencyCode = openOffer.getOffer().getCurrencyCode(); + Optional optionalTriggerPrice = openOffer.getTriggerPrice() > 0 + ? Optional.of(Price.valueOf(currencyCode, openOffer.getTriggerPrice())) + : Optional.empty(); + var preciseTriggerPrice = optionalTriggerPrice.isPresent() + ? reformatMarketPrice(optionalTriggerPrice.get().toPlainString(), currencyCode) + : "0"; return getBuilder(openOffer.getOffer(), true) - .withTriggerPrice(openOffer.getTriggerPrice()) + .withTriggerPrice(preciseTriggerPrice) .withIsActivated(!openOffer.isDeactivated()) .build(); } @@ -203,7 +213,7 @@ public bisq.proto.grpc.OfferInfo toProtoMessage() { .setOfferFeePaymentTxId(isBsqSwapOffer ? "" : offerFeePaymentTxId) .setBuyerSecurityDeposit(buyerSecurityDeposit) .setSellerSecurityDeposit(sellerSecurityDeposit) - .setTriggerPrice(triggerPrice) + .setTriggerPrice(triggerPrice == null ? "0" : triggerPrice) .setIsCurrencyForMakerFeeBtc(isCurrencyForMakerFeeBtc) .setPaymentAccountId(paymentAccountId) .setPaymentMethodId(paymentMethodId) diff --git a/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java b/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java index 556ef9b2a48..1ddb5e92de0 100644 --- a/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java +++ b/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java @@ -44,7 +44,7 @@ public final class OfferInfoBuilder { private String offerFeePaymentTxId; private long buyerSecurityDeposit; private long sellerSecurityDeposit; - private long triggerPrice; + private String triggerPrice; private boolean isCurrencyForMakerFeeBtc; private String paymentAccountId; private String paymentMethodId; @@ -132,7 +132,7 @@ public OfferInfoBuilder withSellerSecurityDeposit(long sellerSecurityDeposit) { return this; } - public OfferInfoBuilder withTriggerPrice(long triggerPrice) { + public OfferInfoBuilder withTriggerPrice(String triggerPrice) { this.triggerPrice = triggerPrice; return this; } From 68450c455f295ec59c77ec1de5e9056654b60028 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 11:24:23 -0300 Subject: [PATCH 12/17] Adjust to `string triggerPrice` change in API cli classes --- cli/src/main/java/bisq/cli/CliMain.java | 5 +-- .../main/java/bisq/cli/CurrencyFormat.java | 4 ++- cli/src/main/java/bisq/cli/GrpcClient.java | 14 ++++----- .../bisq/cli/opts/EditOfferOptionParser.java | 4 --- .../cli/request/OffersServiceRequest.java | 31 +++---------------- .../table/builder/AbstractTableBuilder.java | 3 ++ .../cli/table/builder/OfferTableBuilder.java | 22 ++++++------- .../bisq/cli/table/column/AltcoinColumn.java | 1 + .../bisq/cli/table/column/FiatColumn.java | 1 + 9 files changed, 32 insertions(+), 53 deletions(-) diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java index 4086b8cbcdf..325373f747c 100644 --- a/cli/src/main/java/bisq/cli/CliMain.java +++ b/cli/src/main/java/bisq/cli/CliMain.java @@ -348,7 +348,7 @@ public static void run(String[] args) { var marketPriceMargin = opts.getMktPriceMarginAsBigDecimal(); var securityDeposit = isSwap ? 0.00 : toSecurityDepositAsPct(opts.getSecurityDeposit()); var makerFeeCurrencyCode = opts.getMakerFeeCurrencyCode(); - var triggerPrice = 0; // Cannot be defined until offer is in book. + var triggerPrice = "0"; // Cannot be defined until the new offer is added to book. OfferInfo offer; if (isSwap) { offer = client.createBsqSwapOffer(direction, @@ -388,7 +388,7 @@ public static void run(String[] args) { var fixedPrice = opts.getFixedPrice(); var isUsingMktPriceMargin = opts.isUsingMktPriceMargin(); var marketPriceMargin = opts.getMktPriceMarginAsBigDecimal(); - var triggerPrice = toInternalTriggerPrice(client, offerId, opts.getTriggerPriceAsBigDecimal()); + var triggerPrice = opts.getTriggerPrice(); var enable = opts.getEnableAsSignedInt(); var editOfferType = opts.getOfferEditType(); client.editOffer(offerId, @@ -789,6 +789,7 @@ private static long toLong(String param) { } } + @Deprecated private static long toInternalTriggerPrice(GrpcClient client, String offerId, BigDecimal unscaledTriggerPrice) { diff --git a/cli/src/main/java/bisq/cli/CurrencyFormat.java b/cli/src/main/java/bisq/cli/CurrencyFormat.java index 9f8df8fe88f..ba0e84fca2d 100644 --- a/cli/src/main/java/bisq/cli/CurrencyFormat.java +++ b/cli/src/main/java/bisq/cli/CurrencyFormat.java @@ -123,7 +123,7 @@ public static String formatInternalFiatPrice(double price) { return FRIENDLY_NUMBER_FORMAT.format(price); } - // TODO Deprecate after triggerPrice field type is changed to string. + @Deprecated public static String formatPrice(long price) { FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(4); FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(4); @@ -157,10 +157,12 @@ public static String formatCryptoCurrencyVolume(long volume, int precision) { return FRIENDLY_NUMBER_FORMAT.format((double) volume / SATOSHI_DIVISOR.doubleValue()); } + @Deprecated public static long toInternalFiatPrice(BigDecimal fiatPrice) { return fiatPrice.multiply(new BigDecimal(10_000)).longValue(); } + @Deprecated public static long toInternalCryptoCurrencyPrice(BigDecimal altcoinPrice) { return altcoinPrice.multiply(new BigDecimal(100_000_000)).longValue(); } diff --git a/cli/src/main/java/bisq/cli/GrpcClient.java b/cli/src/main/java/bisq/cli/GrpcClient.java index 897599c66fa..0b9557c58d7 100644 --- a/cli/src/main/java/bisq/cli/GrpcClient.java +++ b/cli/src/main/java/bisq/cli/GrpcClient.java @@ -175,7 +175,7 @@ public OfferInfo createFixedPricedOffer(String direction, securityDeposit, paymentAcctId, makerFeeCurrencyCode, - 0 /* no trigger price */); + "0" /* no trigger price */); } public OfferInfo createMarketBasedPricedOffer(String direction, @@ -186,7 +186,7 @@ public OfferInfo createMarketBasedPricedOffer(String direction, double securityDeposit, String paymentAcctId, String makerFeeCurrencyCode, - long triggerPrice) { + String triggerPrice) { return offersServiceRequest.createOffer(direction, currencyCode, amount, @@ -210,7 +210,7 @@ public OfferInfo createOffer(String direction, double securityDeposit, String paymentAcctId, String makerFeeCurrencyCode, - long triggerPrice) { + String triggerPrice) { return offersServiceRequest.createOffer(direction, currencyCode, amount, @@ -236,22 +236,22 @@ public void editOfferPriceMargin(String offerId, double marketPriceMargin) { offersServiceRequest.editOfferPriceMargin(offerId, marketPriceMargin); } - public void editOfferTriggerPrice(String offerId, long triggerPrice) { + public void editOfferTriggerPrice(String offerId, String triggerPrice) { offersServiceRequest.editOfferTriggerPrice(offerId, triggerPrice); } public void editOffer(String offerId, - String priceAsString, + String price, boolean useMarketBasedPrice, double marketPriceMargin, - long triggerPrice, + String triggerPrice, int enable, EditType editType) { // Take care when using this method directly: // useMarketBasedPrice = true if margin based offer, false for fixed priced offer // scaledPriceString fmt = ######.#### offersServiceRequest.editOffer(offerId, - priceAsString, + price, useMarketBasedPrice, marketPriceMargin, triggerPrice, diff --git a/cli/src/main/java/bisq/cli/opts/EditOfferOptionParser.java b/cli/src/main/java/bisq/cli/opts/EditOfferOptionParser.java index 557a0ff77d4..17afa982f76 100644 --- a/cli/src/main/java/bisq/cli/opts/EditOfferOptionParser.java +++ b/cli/src/main/java/bisq/cli/opts/EditOfferOptionParser.java @@ -215,10 +215,6 @@ public String getTriggerPrice() { } } - public BigDecimal getTriggerPriceAsBigDecimal() { - return new BigDecimal(getTriggerPrice()); - } - public String getMktPriceMargin() { if (offerEditType.equals(MKT_PRICE_MARGIN_ONLY) || offerEditType.equals(MKT_PRICE_MARGIN_AND_ACTIVATION_STATE) diff --git a/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java b/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java index 20b9dc2c024..5f900d770ca 100644 --- a/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java +++ b/cli/src/main/java/bisq/cli/request/OffersServiceRequest.java @@ -95,30 +95,7 @@ public OfferInfo createFixedPricedOffer(String direction, securityDeposit, paymentAcctId, makerFeeCurrencyCode, - 0 /* no trigger price */); - } - - @SuppressWarnings("unused") - public OfferInfo createMarketBasedPricedOffer(String direction, - String currencyCode, - long amount, - long minAmount, - double marketPriceMargin, - double securityDeposit, - String paymentAcctId, - String makerFeeCurrencyCode, - long triggerPrice) { - return createOffer(direction, - currencyCode, - amount, - minAmount, - true, - "0", - marketPriceMargin, - securityDeposit, - paymentAcctId, - makerFeeCurrencyCode, - triggerPrice); + "0" /* no trigger price */); } public OfferInfo createOffer(String direction, @@ -131,7 +108,7 @@ public OfferInfo createOffer(String direction, double securityDeposit, String paymentAcctId, String makerFeeCurrencyCode, - long triggerPrice) { + String triggerPrice) { var request = CreateOfferRequest.newBuilder() .setDirection(direction) .setCurrencyCode(currencyCode) @@ -184,7 +161,7 @@ public void editOfferPriceMargin(String offerId, double marketPriceMargin) { MKT_PRICE_MARGIN_ONLY); } - public void editOfferTriggerPrice(String offerId, long triggerPrice) { + public void editOfferTriggerPrice(String offerId, String triggerPrice) { var offer = getMyOffer(offerId); editOffer(offerId, "0.00", @@ -199,7 +176,7 @@ public void editOffer(String offerId, String scaledPriceString, boolean useMarketBasedPrice, double marketPriceMargin, - long triggerPrice, + String triggerPrice, int enable, EditOfferRequest.EditType editType) { // Take care when using this method directly: diff --git a/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java b/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java index 1484e2c1f93..cdb5f3ffa3f 100644 --- a/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java +++ b/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java @@ -20,6 +20,7 @@ import bisq.proto.grpc.OfferInfo; import java.util.List; +import java.util.function.Function; import java.util.function.Predicate; @@ -31,6 +32,8 @@ */ abstract class AbstractTableBuilder { + protected final Function toBlankOrNonZeroValue = (s) -> s.trim().equals("0") ? "" : s; + protected final TableType tableType; protected final List protos; diff --git a/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java b/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java index e9ddc14e18d..a97c73b848e 100644 --- a/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java +++ b/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java @@ -29,11 +29,9 @@ import static bisq.cli.table.builder.TableBuilderConstants.*; import static bisq.cli.table.builder.TableType.OFFER_TBL; import static bisq.cli.table.column.AltcoinColumn.DISPLAY_MODE.ALTCOIN_OFFER_VOLUME; -import static bisq.cli.table.column.AltcoinColumn.DISPLAY_MODE.ALTCOIN_TRIGGER_PRICE; import static bisq.cli.table.column.Column.JUSTIFICATION.LEFT; import static bisq.cli.table.column.Column.JUSTIFICATION.NONE; import static bisq.cli.table.column.Column.JUSTIFICATION.RIGHT; -import static bisq.cli.table.column.FiatColumn.DISPLAY_MODE.TRIGGER_PRICE; import static bisq.cli.table.column.FiatColumn.DISPLAY_MODE.VOLUME; import static bisq.cli.table.column.ZippedStringColumns.DUPLICATION_MODE.EXCLUDE_DUPLICATES; import static java.lang.String.format; @@ -84,7 +82,7 @@ public Table buildFiatOfferTable(List offers) { Column colFiatVolume = new FiatColumn(format("Temp Volume (%s)", fiatTradeCurrency.get()), NONE, VOLUME); Column colMinFiatVolume = new FiatColumn(format("Temp Min Volume (%s)", fiatTradeCurrency.get()), NONE, VOLUME); @Nullable - Column colTriggerPrice = fiatTriggerPriceColumn.get(); + Column colTriggerPrice = fiatTriggerPriceColumn.get(); // Populate columns with offer info. @@ -101,7 +99,7 @@ public Table buildFiatOfferTable(List offers) { colFiatVolume.addRow(o.getVolume()); if (colTriggerPrice != null) - colTriggerPrice.addRow(o.getTriggerPrice()); + colTriggerPrice.addRow(toBlankOrNonZeroValue.apply(o.getTriggerPrice())); colPaymentMethod.addRow(o.getPaymentMethodShortName()); colCreateDate.addRow(o.getDate()); @@ -124,7 +122,7 @@ public Table buildFiatOfferTable(List offers) { colFiatPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), - colTriggerPrice.asStringColumn(), + colTriggerPrice.justify(), colPaymentMethod, colCreateDate.asStringColumn(), colOfferId); @@ -151,7 +149,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { NONE, ALTCOIN_OFFER_VOLUME); @Nullable - Column colTriggerPrice = altcoinTriggerPriceColumn.get(); + Column colTriggerPrice = altcoinTriggerPriceColumn.get(); // Populate columns with offer info. @@ -168,7 +166,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { colMinBtcVolume.addRow(o.getVolume()); if (colTriggerPrice != null) - colTriggerPrice.addRow(o.getTriggerPrice()); + colTriggerPrice.addRow(toBlankOrNonZeroValue.apply(o.getTriggerPrice())); colPaymentMethod.addRow(o.getPaymentMethodShortName()); colCreateDate.addRow(o.getDate()); @@ -201,7 +199,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { colBtcPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), - colTriggerPrice.asStringColumn(), + colTriggerPrice.justify(), colPaymentMethod, colCreateDate.asStringColumn(), colOfferId); @@ -231,14 +229,14 @@ public Table buildCryptoCurrencyOfferTable(List offers) { ? new StringColumn(COL_HEADER_ENABLED, LEFT) : null; @Nullable - private final Supplier fiatTriggerPriceColumn = () -> + private final Supplier fiatTriggerPriceColumn = () -> isShowingMyOffers.get() - ? new FiatColumn(format(COL_HEADER_TRIGGER_PRICE, fiatTradeCurrency.get()), RIGHT, TRIGGER_PRICE) + ? new StringColumn(format(COL_HEADER_TRIGGER_PRICE, fiatTradeCurrency.get()), RIGHT) : null; @Nullable - private final Supplier altcoinTriggerPriceColumn = () -> + private final Supplier altcoinTriggerPriceColumn = () -> isShowingMyOffers.get() && !isShowingBsqOffers.get() - ? new AltcoinColumn(format(COL_HEADER_TRIGGER_PRICE, altcoinTradeCurrency.get()), RIGHT, ALTCOIN_TRIGGER_PRICE) + ? new StringColumn(format(COL_HEADER_TRIGGER_PRICE, altcoinTradeCurrency.get()), RIGHT) : null; private final Function toEnabled = (o) -> { diff --git a/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java b/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java index 4c59eb03324..3b13171f7f7 100644 --- a/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java +++ b/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java @@ -34,6 +34,7 @@ public class AltcoinColumn extends LongColumn { public enum DISPLAY_MODE { ALTCOIN_OFFER_VOLUME, ALTCOIN_PRICE, + @Deprecated ALTCOIN_TRIGGER_PRICE } diff --git a/cli/src/main/java/bisq/cli/table/column/FiatColumn.java b/cli/src/main/java/bisq/cli/table/column/FiatColumn.java index e9b940ee9d7..9adb9de5a01 100644 --- a/cli/src/main/java/bisq/cli/table/column/FiatColumn.java +++ b/cli/src/main/java/bisq/cli/table/column/FiatColumn.java @@ -33,6 +33,7 @@ public class FiatColumn extends LongColumn { public enum DISPLAY_MODE { PRICE, + @Deprecated TRIGGER_PRICE, VOLUME } From 2af3ac22a3bde286d94258612e1741951953d491 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 11:25:18 -0300 Subject: [PATCH 13/17] Adjust to `string triggerPrice` change in API test cases --- .../method/offer/AbstractOfferTest.java | 19 +--- ...CreateOfferUsingMarketPriceMarginTest.java | 10 +- .../method/offer/CreateXMROffersTest.java | 8 +- .../apitest/method/offer/EditOfferTest.java | 100 +++++++++--------- .../LongRunningOfferDeactivationTest.java | 22 ++-- .../bisq/apitest/scenario/bot/BotClient.java | 3 +- .../apitest/scenario/bot/RandomOffer.java | 2 +- 7 files changed, 71 insertions(+), 93 deletions(-) diff --git a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java index e014792565a..35a33c45c61 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/AbstractOfferTest.java @@ -28,7 +28,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.function.BiFunction; import java.util.function.Function; import lombok.Setter; @@ -63,7 +62,7 @@ public abstract class AbstractOfferTest extends MethodTest { protected static final int ACTIVATE_OFFER = 1; protected static final int DEACTIVATE_OFFER = 0; - protected static final long NO_TRIGGER_PRICE = 0; + protected static final String NO_TRIGGER_PRICE = "0"; @Setter protected static boolean isLongRunningTest; @@ -95,22 +94,6 @@ public static void setUp() { protected final Function scaledDownMktPriceMargin = (mktPriceMargin) -> exactMultiply(mktPriceMargin, 0.01); - // Price value of fiat offer returned from server will be scaled up by 10^4. - protected final Function scaledUpFiatOfferPrice = (price) -> { - BigDecimal factor = new BigDecimal(10).pow(4); - return price.multiply(factor).longValue(); - }; - - protected final BiFunction calcFiatTriggerPriceAsLong = (base, delta) -> { - var priceAsDouble = new BigDecimal(base).add(new BigDecimal(delta)).doubleValue(); - return Double.valueOf(exactMultiply(priceAsDouble, 10_000)).longValue(); - }; - - protected final BiFunction calcAltcoinTriggerPriceAsLong = (base, delta) -> { - var priceAsDouble = new BigDecimal(base).add(new BigDecimal(delta)).doubleValue(); - return Double.valueOf(exactMultiply(priceAsDouble, 100_000_000)).longValue(); - }; - protected final Function toOfferTable = (offer) -> new TableBuilder(OFFER_TBL, offer).build().toString(); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java index a4f7f23e993..2dd32d44d3d 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java @@ -17,7 +17,6 @@ package bisq.apitest.method.offer; -import bisq.core.monetary.Price; import bisq.core.payment.PaymentAccount; import bisq.proto.grpc.OfferInfo; @@ -255,10 +254,7 @@ public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() { public void testCreateUSDBTCBuyOfferWithTriggerPrice() { PaymentAccount usdAccount = createDummyF2FAccount(aliceClient, "US"); double mktPriceAsDouble = aliceClient.getBtcPrice("usd"); - BigDecimal mktPrice = new BigDecimal(Double.toString(mktPriceAsDouble)); - BigDecimal triggerPrice = mktPrice.add(new BigDecimal("1000.9999")); - long triggerPriceAsLong = Price.parse(USD, triggerPrice.toString()).getValue(); - + String triggerPrice = calcPriceAsString(mktPriceAsDouble, Double.parseDouble("1000.9999"), 4); var newOffer = aliceClient.createMarketBasedPricedOffer(BUY.name(), "usd", 10_000_000L, @@ -267,7 +263,7 @@ public void testCreateUSDBTCBuyOfferWithTriggerPrice() { getDefaultBuyerSecurityDepositAsPercent(), usdAccount.getId(), MAKER_FEE_CURRENCY_CODE, - triggerPriceAsLong); + triggerPrice); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -276,7 +272,7 @@ public void testCreateUSDBTCBuyOfferWithTriggerPrice() { log.debug("OFFER #5:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); - assertEquals(triggerPriceAsLong, newOffer.getTriggerPrice()); + assertEquals(triggerPrice, newOffer.getTriggerPrice()); } private void assertCalculatedPriceIsCorrect(OfferInfo offer, double priceMarginPctInput) { diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java index b945238d7ea..33fad708d85 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateXMROffersTest.java @@ -156,7 +156,7 @@ public void testCreateFixedPriceSell1BTCFor200KXMROffer() { public void testCreatePriceMarginBasedBuy1BTCOfferWithTriggerPrice() { double priceMarginPctInput = 1.00; double mktPriceAsDouble = aliceClient.getBtcPrice(XMR); - long triggerPriceAsLong = calcAltcoinTriggerPriceAsLong.apply(mktPriceAsDouble, -0.001); + String triggerPrice = calcPriceAsString(mktPriceAsDouble, Double.parseDouble("-0.001"), 8); var newOffer = aliceClient.createMarketBasedPricedOffer(BUY.name(), XMR, 100_000_000L, @@ -165,7 +165,7 @@ public void testCreatePriceMarginBasedBuy1BTCOfferWithTriggerPrice() { getDefaultBuyerSecurityDepositAsPercent(), alicesXmrAcct.getId(), MAKER_FEE_CURRENCY_CODE, - triggerPriceAsLong); + triggerPrice); log.debug("Pending Sell XMR (Buy BTC) offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -176,7 +176,7 @@ public void testCreatePriceMarginBasedBuy1BTCOfferWithTriggerPrice() { assertTrue(newOffer.getUseMarketBasedPrice()); // There is no trigger price while offer is pending. - assertEquals(0, newOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, newOffer.getTriggerPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(75_000_000L, newOffer.getMinAmount()); @@ -197,7 +197,7 @@ public void testCreatePriceMarginBasedBuy1BTCOfferWithTriggerPrice() { assertTrue(newOffer.getUseMarketBasedPrice()); // The trigger price should exist on the prepared offer. - assertEquals(triggerPriceAsLong, newOffer.getTriggerPrice()); + assertEquals(triggerPrice, newOffer.getTriggerPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(75_000_000L, newOffer.getMinAmount()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java b/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java index b0401c6522b..55b041ed3c1 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/EditOfferTest.java @@ -100,18 +100,18 @@ public void testEditTriggerPrice() { log.debug("Original EUR offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); - assertEquals(0 /*no trigger price*/, originalOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, originalOffer.getTriggerPrice()); // Edit the offer's trigger price, nothing else. var mktPrice = aliceClient.getBtcPrice(EUR); var delta = 5_000.00; - var newTriggerPriceAsLong = calcFiatTriggerPriceAsLong.apply(mktPrice, delta); + var newTriggerPrice = calcPriceAsString(mktPrice, delta, 4); - aliceClient.editOfferTriggerPrice(originalOffer.getId(), newTriggerPriceAsLong); + aliceClient.editOfferTriggerPrice(originalOffer.getId(), newTriggerPrice); sleep(2_500); // Wait for offer book re-entry. OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited EUR offer:\n{}", toOfferTable.apply(editedOffer)); - assertEquals(newTriggerPriceAsLong, editedOffer.getTriggerPrice()); + assertEquals(newTriggerPrice, editedOffer.getTriggerPrice()); assertTrue(editedOffer.getUseMarketBasedPrice()); doSanityCheck(originalOffer, editedOffer); @@ -130,7 +130,7 @@ public void testSetTriggerPriceToNegativeValueShouldThrowException() { genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. // Edit the offer's trigger price, set to -1, check error. Throwable exception = assertThrows(StatusRuntimeException.class, () -> - aliceClient.editOfferTriggerPrice(originalOffer.getId(), -1L)); + aliceClient.editOfferTriggerPrice(originalOffer.getId(), "-1")); String expectedExceptionMessage = format("UNKNOWN: programmer error: cannot set trigger price to a negative value in offer with id '%s'", originalOffer.getId()); @@ -228,7 +228,7 @@ public void testEditMktPriceMarginAndDeactivation() { USD, paymentAcct.getId(), originalMktPriceMargin, - 0); + NO_TRIGGER_PRICE); log.debug("Original USD offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); @@ -240,7 +240,7 @@ public void testEditMktPriceMarginAndDeactivation() { "0.00", originalOffer.getUseMarketBasedPrice(), newMktPriceMargin, - 0, + NO_TRIGGER_PRICE, DEACTIVATE_OFFER, MKT_PRICE_MARGIN_AND_ACTIVATION_STATE); // Wait for edited offer to be removed from offer-book, edited, and re-published. @@ -248,7 +248,7 @@ public void testEditMktPriceMarginAndDeactivation() { OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited USD offer:\n{}", toOfferTable.apply(editedOffer)); assertEquals(scaledDownMktPriceMargin.apply(newMktPriceMargin), editedOffer.getMarketPriceMargin()); - assertEquals(0, editedOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, editedOffer.getTriggerPrice()); assertFalse(editedOffer.getIsActivated()); assertTrue(editedOffer.getUseMarketBasedPrice()); @@ -261,26 +261,26 @@ public void testEditMktPriceMarginAndTriggerPriceAndDeactivation() { PaymentAccount paymentAcct = getOrCreatePaymentAccount("US"); var originalMktPriceMargin = new BigDecimal("0.0").doubleValue(); var mktPriceAsDouble = aliceClient.getBtcPrice(USD); - var originalTriggerPriceAsLong = calcFiatTriggerPriceAsLong.apply(mktPriceAsDouble, -5_000.0000); + var originalTriggerPrice = calcPriceAsString(mktPriceAsDouble, -5_000.0000, 4); OfferInfo originalOffer = createMktPricedOfferForEdit(SELL.name(), USD, paymentAcct.getId(), originalMktPriceMargin, - originalTriggerPriceAsLong); + originalTriggerPrice); log.debug("Original USD offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. originalOffer = aliceClient.getOffer(originalOffer.getId()); assertEquals(scaledDownMktPriceMargin.apply(originalMktPriceMargin), originalOffer.getMarketPriceMargin()); - assertEquals(originalTriggerPriceAsLong, originalOffer.getTriggerPrice()); + assertEquals(originalTriggerPrice, originalOffer.getTriggerPrice()); // Edit the offer's price margin and trigger price, and deactivate it. var newMktPriceMargin = new BigDecimal("0.1").doubleValue(); - var newTriggerPriceAsLong = calcFiatTriggerPriceAsLong.apply(mktPriceAsDouble, -2_000.0000); + var newTriggerPrice = calcPriceAsString(mktPriceAsDouble, -2_000.0000, 4); aliceClient.editOffer(originalOffer.getId(), "0.00", originalOffer.getUseMarketBasedPrice(), newMktPriceMargin, - newTriggerPriceAsLong, + newTriggerPrice, DEACTIVATE_OFFER, MKT_PRICE_MARGIN_AND_TRIGGER_PRICE_AND_ACTIVATION_STATE); // Wait for edited offer to be removed from offer-book, edited, and re-published. @@ -288,7 +288,7 @@ public void testEditMktPriceMarginAndTriggerPriceAndDeactivation() { OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited USD offer:\n{}", toOfferTable.apply(editedOffer)); assertEquals(scaledDownMktPriceMargin.apply(newMktPriceMargin), editedOffer.getMarketPriceMargin()); - assertEquals(newTriggerPriceAsLong, editedOffer.getTriggerPrice()); + assertEquals(newTriggerPrice, editedOffer.getTriggerPrice()); assertFalse(editedOffer.getIsActivated()); doSanityCheck(originalOffer, editedOffer); @@ -337,7 +337,7 @@ public void testEditingTriggerPriceInFixedPriceOfferShouldThrowException() { fixedPriceAsString); log.debug("Original RUB offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. - long newTriggerPrice = 1000000L; + var newTriggerPrice = "1000000"; Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOfferTriggerPrice(originalOffer.getId(), newTriggerPrice)); String expectedExceptionMessage = @@ -363,12 +363,12 @@ public void testChangeFixedPriceOfferToPriceMarginBasedOfferWithTriggerPrice() { // Change the offer to mkt price based and set a trigger price. var newMktPriceMargin = new BigDecimal("0.05").doubleValue(); var delta = 200_000.0000; // trigger price on buy offer is 200K above mkt price - var newTriggerPriceAsLong = calcFiatTriggerPriceAsLong.apply(mktPriceAsDouble, delta); + var newTriggerPrice = calcPriceAsString(mktPriceAsDouble, delta, 4); aliceClient.editOffer(originalOffer.getId(), "0.00", true, newMktPriceMargin, - newTriggerPriceAsLong, + newTriggerPrice, ACTIVATE_OFFER, MKT_PRICE_MARGIN_AND_TRIGGER_PRICE); // Wait for edited offer to be removed from offer-book, edited, and re-published. @@ -377,7 +377,7 @@ public void testChangeFixedPriceOfferToPriceMarginBasedOfferWithTriggerPrice() { log.debug("Edited MXN offer:\n{}", toOfferTable.apply(editedOffer)); assertTrue(editedOffer.getUseMarketBasedPrice()); assertEquals(scaledDownMktPriceMargin.apply(newMktPriceMargin), editedOffer.getMarketPriceMargin()); - assertEquals(newTriggerPriceAsLong, editedOffer.getTriggerPrice()); + assertEquals(newTriggerPrice, editedOffer.getTriggerPrice()); assertTrue(editedOffer.getIsActivated()); doSanityCheck(originalOffer, editedOffer); @@ -390,7 +390,7 @@ public void testChangePriceMarginBasedOfferToFixedPriceOfferAndDeactivateIt() { double mktPriceAsDouble = aliceClient.getBtcPrice("GBP"); var originalMktPriceMargin = new BigDecimal("0.25").doubleValue(); var delta = 1_000.0000; // trigger price on sell offer is 1K below mkt price - var originalTriggerPriceAsLong = calcFiatTriggerPriceAsLong.apply(mktPriceAsDouble, delta); + var originalTriggerPriceAsLong = calcPriceAsString(mktPriceAsDouble, delta, 4); var originalOffer = createMktPricedOfferForEdit(SELL.name(), "GBP", paymentAcct.getId(), @@ -404,7 +404,7 @@ public void testChangePriceMarginBasedOfferToFixedPriceOfferAndDeactivateIt() { fixedPriceAsString, false, 0.00, - 0, + NO_TRIGGER_PRICE, DEACTIVATE_OFFER, FIXED_PRICE_AND_ACTIVATION_STATE); // Wait for edited offer to be removed from offer-book, edited, and re-published. @@ -414,7 +414,7 @@ public void testChangePriceMarginBasedOfferToFixedPriceOfferAndDeactivateIt() { assertEquals(fixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); - assertEquals(0, editedOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, editedOffer.getTriggerPrice()); assertFalse(editedOffer.getIsActivated()); } @@ -436,7 +436,7 @@ public void testChangeFixedPricedBsqOfferToPriceMarginBasedOfferShouldThrowExcep "0.00", true, 0.1, - 0, + NO_TRIGGER_PRICE, ACTIVATE_OFFER, MKT_PRICE_MARGIN_ONLY)); String expectedExceptionMessage = format("UNKNOWN: cannot set mkt price margin or" @@ -458,7 +458,7 @@ public void testEditTriggerPriceOnFixedPriceBsqOfferShouldThrowException() { BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2_500); // Wait for entry into offer book. - var newTriggerPriceAsLong = calcFiatTriggerPriceAsLong.apply(0.00005, 0.00); + var newTriggerPriceAsLong = calcPriceAsString(0.00005, 0.00, 8); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOffer(originalOffer.getId(), "0.00", @@ -492,7 +492,7 @@ public void testEditFixedPriceOnBsqOffer() { newFixedPriceAsString, false, 0.0, - 0, + NO_TRIGGER_PRICE, ACTIVATE_OFFER, FIXED_PRICE_ONLY); // Wait for edited offer to be edited and removed from offer-book. @@ -503,7 +503,7 @@ public void testEditFixedPriceOnBsqOffer() { assertTrue(editedOffer.getIsActivated()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); - assertEquals(0, editedOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, editedOffer.getTriggerPrice()); } @Test @@ -524,7 +524,7 @@ public void testDisableBsqOffer() { fixedPriceAsString, false, 0.0, - 0, + NO_TRIGGER_PRICE, DEACTIVATE_OFFER, ACTIVATION_STATE_ONLY); // Wait for edited offer to be removed from offer-book. @@ -535,7 +535,7 @@ public void testDisableBsqOffer() { assertEquals(fixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); - assertEquals(0, editedOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, editedOffer.getTriggerPrice()); } @Test @@ -557,7 +557,7 @@ public void testEditFixedPriceAndDisableBsqOffer() { newFixedPriceAsString, false, 0.0, - 0, + NO_TRIGGER_PRICE, DEACTIVATE_OFFER, FIXED_PRICE_AND_ACTIVATION_STATE); // Wait for edited offer to be edited and removed from offer-book. @@ -568,7 +568,7 @@ public void testEditFixedPriceAndDisableBsqOffer() { assertEquals(newFixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); - assertEquals(0, editedOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, editedOffer.getTriggerPrice()); } // Edit XMR Offers @@ -578,12 +578,12 @@ public void testEditFixedPriceAndDisableBsqOffer() { public void testChangePriceMarginBasedXmrOfferWithTriggerPriceToFixedPricedAndDeactivateIt() { createXmrPaymentAccounts(); double mktPriceAsDouble = aliceClient.getBtcPrice(XMR); - long triggerPriceAsLong = calcAltcoinTriggerPriceAsLong.apply(mktPriceAsDouble, 0.001); + String triggerPrice = calcPriceAsString(mktPriceAsDouble, 0.001, 8); OfferInfo originalOffer = createMktPricedOfferForEdit(SELL.name(), XMR, alicesXmrAcct.getId(), 0.0, - triggerPriceAsLong); + triggerPrice); log.debug("Pending XMR offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. @@ -595,7 +595,7 @@ public void testChangePriceMarginBasedXmrOfferWithTriggerPriceToFixedPricedAndDe newFixedPriceAsString, false, 0.00, - 0, + NO_TRIGGER_PRICE, DEACTIVATE_OFFER, FIXED_PRICE_AND_ACTIVATION_STATE); // Wait for edited offer to be removed from offer-book, edited & not re-published. @@ -605,7 +605,7 @@ public void testChangePriceMarginBasedXmrOfferWithTriggerPriceToFixedPricedAndDe assertEquals(newFixedPriceAsString, editedOffer.getPrice()); assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); - assertEquals(0, editedOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, editedOffer.getTriggerPrice()); assertFalse(editedOffer.getIsActivated()); doSanityCheck(originalOffer, editedOffer); @@ -628,12 +628,12 @@ public void testEditTriggerPriceOnPriceMarginBasedXmrOffer() { log.info("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); double mktPriceAsDouble = aliceClient.getBtcPrice(XMR); - long triggerPriceAsLong = calcAltcoinTriggerPriceAsLong.apply(mktPriceAsDouble, 0.001); + String triggerPrice = calcPriceAsString(mktPriceAsDouble, 0.001, 8); aliceClient.editOffer(originalOffer.getId(), "0", true, mktPriceMargin, - triggerPriceAsLong, + triggerPrice, ACTIVATE_OFFER, TRIGGER_PRICE_ONLY); // Wait for edited offer to be removed from offer-book, edited & not re-published. @@ -642,7 +642,7 @@ public void testEditTriggerPriceOnPriceMarginBasedXmrOffer() { log.info("Edited XMR offer:\n{}", toOfferTable.apply(editedOffer)); assertTrue(editedOffer.getUseMarketBasedPrice()); assertEquals(scaledDownMktPriceMargin.apply(mktPriceMargin), editedOffer.getMarketPriceMargin()); - assertEquals(triggerPriceAsLong, editedOffer.getTriggerPrice()); + assertEquals(triggerPrice, editedOffer.getTriggerPrice()); assertTrue(editedOffer.getIsActivated()); doSanityCheck(originalOffer, editedOffer); @@ -671,12 +671,12 @@ public void testChangeFixedPricedXmrOfferToPriceMarginBasedOfferWithTriggerPrice // Change the offer to mkt price based and set a trigger price. var newMktPriceMargin = new BigDecimal("0.05").doubleValue(); var delta = -0.00100000; - var newTriggerPriceAsLong = calcAltcoinTriggerPriceAsLong.apply(mktPriceAsDouble, delta); + var newTriggerPrice = calcPriceAsString(mktPriceAsDouble, delta, 8); aliceClient.editOffer(originalOffer.getId(), "0.00", true, newMktPriceMargin, - newTriggerPriceAsLong, + newTriggerPrice, ACTIVATE_OFFER, MKT_PRICE_MARGIN_AND_TRIGGER_PRICE); // Wait for edited offer to be removed from offer-book, edited, and re-published. @@ -685,7 +685,7 @@ public void testChangeFixedPricedXmrOfferToPriceMarginBasedOfferWithTriggerPrice log.debug("Edited XMR offer:\n{}", toOfferTable.apply(editedOffer)); assertTrue(editedOffer.getUseMarketBasedPrice()); assertEquals(scaledDownMktPriceMargin.apply(newMktPriceMargin), editedOffer.getMarketPriceMargin()); - assertEquals(newTriggerPriceAsLong, editedOffer.getTriggerPrice()); + assertEquals(newTriggerPrice, editedOffer.getTriggerPrice()); assertTrue(editedOffer.getIsActivated()); doSanityCheck(originalOffer, editedOffer); @@ -706,13 +706,13 @@ public void testEditTriggerPriceOnFixedPriceXmrOfferShouldThrowException() { log.debug("Original XMR offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. - var newTriggerPriceAsLong = calcAltcoinTriggerPriceAsLong.apply(0.007, 0.001); + var newTriggerPrice = calcPriceAsString(0.007, 0.001, 8); Throwable exception = assertThrows(StatusRuntimeException.class, () -> aliceClient.editOffer(originalOffer.getId(), "0.00", false, 0.1, - newTriggerPriceAsLong, + newTriggerPrice, ACTIVATE_OFFER, TRIGGER_PRICE_ONLY)); String expectedExceptionMessage = format("UNKNOWN: programmer error: cannot set a trigger price" @@ -736,19 +736,19 @@ public void testEditFixedPriceOnXmrOffer() { BSQ); log.debug("Original BSQ offer:\n{}", toOfferTable.apply(originalOffer)); genBtcBlocksThenWait(1, 2500); // Wait for entry into offer book. - String newFixedPriceAsString = "0.00900000"; + String newFixedPrice = "0.00900000"; aliceClient.editOffer(originalOffer.getId(), - newFixedPriceAsString, + newFixedPrice, false, 0.0, - 0, + NO_TRIGGER_PRICE, ACTIVATE_OFFER, FIXED_PRICE_ONLY); // Wait for edited offer to be edited and removed from offer-book. genBtcBlocksThenWait(1, 2500); OfferInfo editedOffer = aliceClient.getOffer(originalOffer.getId()); log.debug("Edited XMR offer:\n{}", toOfferTable.apply(editedOffer)); - assertEquals(newFixedPriceAsString, editedOffer.getPrice()); + assertEquals(newFixedPrice, editedOffer.getPrice()); assertTrue(editedOffer.getIsActivated()); assertMarketBasedPriceFieldsAreIgnored(editedOffer); @@ -774,7 +774,7 @@ public void testDisableXmrOffer() { fixedPriceAsString, false, 0.0, - 0, + NO_TRIGGER_PRICE, DEACTIVATE_OFFER, ACTIVATION_STATE_ONLY); // Wait for edited offer to be removed from offer-book. @@ -808,7 +808,7 @@ public void testEditFixedPriceAndDisableXmrOffer() { newFixedPriceAsString, false, 0.0, - 0, + NO_TRIGGER_PRICE, DEACTIVATE_OFFER, FIXED_PRICE_AND_ACTIVATION_STATE); // Wait for edited offer to be edited and removed from offer-book. @@ -849,7 +849,7 @@ public void testEditBsqSwapOfferShouldThrowException() { newFixedPrice, false, 0.0, - 0, + NO_TRIGGER_PRICE, ACTIVATE_OFFER, TRIGGER_PRICE_ONLY)); String expectedExceptionMessage = format("UNKNOWN: cannot edit bsq swap offer with id '%s'", @@ -861,7 +861,7 @@ private OfferInfo createMktPricedOfferForEdit(String direction, String currencyCode, String paymentAccountId, double marketPriceMargin, - long triggerPrice) { + String triggerPrice) { return aliceClient.createMarketBasedPricedOffer(direction, currencyCode, AMOUNT, @@ -905,7 +905,7 @@ private void doSanityCheck(OfferInfo originalOffer, OfferInfo editedOffer) { private void assertMarketBasedPriceFieldsAreIgnored(OfferInfo editedOffer) { assertFalse(editedOffer.getUseMarketBasedPrice()); assertEquals(0.00, editedOffer.getMarketPriceMargin()); - assertEquals(0, editedOffer.getTriggerPrice()); + assertEquals(NO_TRIGGER_PRICE, editedOffer.getTriggerPrice()); } private PaymentAccount getOrCreatePaymentAccount(String countryCode) { diff --git a/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java b/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java index 7dee678d2c6..a27fa8174d4 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java +++ b/apitest/src/test/java/bisq/apitest/scenario/LongRunningOfferDeactivationTest.java @@ -31,7 +31,6 @@ import org.junit.jupiter.api.condition.EnabledIf; import static bisq.apitest.config.ApiTestConfig.BTC; -import static bisq.cli.CurrencyFormat.formatPrice; import static bisq.core.btc.wallet.Restrictions.getDefaultBuyerSecurityDepositAsPercent; import static java.lang.System.getenv; import static org.junit.jupiter.api.Assertions.fail; @@ -59,8 +58,8 @@ public class LongRunningOfferDeactivationTest extends AbstractOfferTest { public void testSellOfferAutoDisable(final TestInfo testInfo) { PaymentAccount paymentAcct = createDummyF2FAccount(aliceClient, "US"); double mktPriceAsDouble = aliceClient.getBtcPrice("USD"); - long triggerPrice = calcFiatTriggerPriceAsLong.apply(mktPriceAsDouble, -50.0000); - log.info("Current USD mkt price = {} Trigger Price = {}", mktPriceAsDouble, formatPrice(triggerPrice)); + String triggerPrice = calcPriceAsString(mktPriceAsDouble, -50.0000, 4); + log.info("Current USD mkt price = {} Trigger Price = {}", mktPriceAsDouble, triggerPrice); OfferInfo offer = aliceClient.createMarketBasedPricedOffer(SELL.name(), "USD", 1_000_000, @@ -76,8 +75,7 @@ public void testSellOfferAutoDisable(final TestInfo testInfo) { genBtcBlocksThenWait(1, 2500); // Wait for offer book entry. offer = aliceClient.getOffer(offer.getId()); // Offer has trigger price now. - log.info("SELL offer should be automatically disabled when mkt price falls below {}.", - formatPrice(offer.getTriggerPrice())); + log.info("SELL offer should be automatically disabled when mkt price falls below {}.", offer.getTriggerPrice()); int numIterations = 0; while (++numIterations < MAX_ITERATIONS) { @@ -87,12 +85,12 @@ public void testSellOfferAutoDisable(final TestInfo testInfo) { if (offer.getIsActivated()) { log.info("Offer still enabled at mkt price {} > {} trigger price", mktPrice, - formatPrice(offer.getTriggerPrice())); + offer.getTriggerPrice()); sleep(1000 * 60); // 60s } else { log.info("Successful test completion after offer disabled at mkt price {} < {} trigger price.", mktPrice, - formatPrice(offer.getTriggerPrice())); + offer.getTriggerPrice()); break; } if (numIterations == MAX_ITERATIONS) @@ -107,8 +105,8 @@ public void testSellOfferAutoDisable(final TestInfo testInfo) { public void testBuyOfferAutoDisable(final TestInfo testInfo) { PaymentAccount paymentAcct = createDummyF2FAccount(aliceClient, "US"); double mktPriceAsDouble = aliceClient.getBtcPrice("USD"); - long triggerPrice = calcFiatTriggerPriceAsLong.apply(mktPriceAsDouble, 50.0000); - log.info("Current USD mkt price = {} Trigger Price = {}", mktPriceAsDouble, formatPrice(triggerPrice)); + String triggerPrice = calcPriceAsString(mktPriceAsDouble, 50.0000, 4); + log.info("Current USD mkt price = {} Trigger Price = {}", mktPriceAsDouble, triggerPrice); OfferInfo offer = aliceClient.createMarketBasedPricedOffer(BUY.name(), "USD", 1_000_000, @@ -125,7 +123,7 @@ public void testBuyOfferAutoDisable(final TestInfo testInfo) { offer = aliceClient.getOffer(offer.getId()); // Offer has trigger price now. log.info("BUY offer should be automatically disabled when mkt price rises above {}.", - formatPrice(offer.getTriggerPrice())); + offer.getTriggerPrice()); int numIterations = 0; while (++numIterations < MAX_ITERATIONS) { @@ -135,12 +133,12 @@ public void testBuyOfferAutoDisable(final TestInfo testInfo) { if (offer.getIsActivated()) { log.info("Offer still enabled at mkt price {} < {} trigger price", mktPrice, - formatPrice(offer.getTriggerPrice())); + offer.getTriggerPrice()); sleep(1000 * 60); // 60s } else { log.info("Successful test completion after offer disabled at mkt price {} > {} trigger price.", mktPrice, - formatPrice(offer.getTriggerPrice())); + offer.getTriggerPrice()); break; } if (numIterations == MAX_ITERATIONS) diff --git a/apitest/src/test/java/bisq/apitest/scenario/bot/BotClient.java b/apitest/src/test/java/bisq/apitest/scenario/bot/BotClient.java index 3ae53d7d55c..2a32aa77a54 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/bot/BotClient.java +++ b/apitest/src/test/java/bisq/apitest/scenario/bot/BotClient.java @@ -120,6 +120,7 @@ public List getSellOffers(String currencyCode) { * @param priceMarginAsPercent * @param securityDepositAsPercent * @param feeCurrency + * @param triggerPrice * @return OfferInfo */ public OfferInfo createOfferAtMarketBasedPrice(PaymentAccount paymentAccount, @@ -130,7 +131,7 @@ public OfferInfo createOfferAtMarketBasedPrice(PaymentAccount paymentAccount, double priceMarginAsPercent, double securityDepositAsPercent, String feeCurrency, - long triggerPrice) { + String triggerPrice) { return grpcClient.createMarketBasedPricedOffer(direction, currencyCode, amountInSatoshis, diff --git a/apitest/src/test/java/bisq/apitest/scenario/bot/RandomOffer.java b/apitest/src/test/java/bisq/apitest/scenario/bot/RandomOffer.java index de728aa76e9..5f6cf143d43 100644 --- a/apitest/src/test/java/bisq/apitest/scenario/bot/RandomOffer.java +++ b/apitest/src/test/java/bisq/apitest/scenario/bot/RandomOffer.java @@ -129,7 +129,7 @@ public RandomOffer create() throws InvalidRandomOfferException { priceMargin, getDefaultBuyerSecurityDepositAsPercent(), feeCurrency, - 0 /*no trigger price*/); + "0" /*no trigger price*/); } else { this.offer = botClient.createOfferAtFixedPrice(paymentAccount, direction, From d42c58073fa30df50ea3f36e75badb0578182ea0 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 16:43:23 -0300 Subject: [PATCH 14/17] Change OfferInfo proto's volume fields' type to string --- .../java/bisq/core/api/model/OfferInfo.java | 18 +++++++++++------- .../api/model/builder/OfferInfoBuilder.java | 8 ++++---- proto/src/main/proto/grpc.proto | 16 ++++++---------- 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/bisq/core/api/model/OfferInfo.java b/core/src/main/java/bisq/core/api/model/OfferInfo.java index c3703d2ab42..48a15be9425 100644 --- a/core/src/main/java/bisq/core/api/model/OfferInfo.java +++ b/core/src/main/java/bisq/core/api/model/OfferInfo.java @@ -32,6 +32,7 @@ import lombok.ToString; import static bisq.core.util.PriceUtil.reformatMarketPrice; +import static bisq.core.util.VolumeUtil.formatVolume; import static java.util.Objects.requireNonNull; @EqualsAndHashCode @@ -50,8 +51,8 @@ public class OfferInfo implements Payload { private final double marketPriceMargin; private final long amount; private final long minAmount; - private final long volume; - private final long minVolume; + private final String volume; + private final String minVolume; private final long txFee; private final long makerFee; private final String offerFeePaymentTxId; @@ -147,9 +148,12 @@ public static OfferInfo toMyOfferInfo(OpenOffer openOffer) { } private static OfferInfoBuilder getBuilder(Offer offer, boolean isMyOffer) { + var currencyCode = offer.getCurrencyCode(); var preciseOfferPrice = reformatMarketPrice( requireNonNull(offer.getPrice()).toPlainString(), - offer.getCurrencyCode()); + currencyCode); + var roundedVolume = formatVolume(requireNonNull(offer.getVolume())); + var roundedMinVolume = formatVolume(requireNonNull(offer.getMinVolume())); return new OfferInfoBuilder() .withId(offer.getId()) .withDirection(offer.getDirection().name()) @@ -158,8 +162,8 @@ private static OfferInfoBuilder getBuilder(Offer offer, boolean isMyOffer) { .withMarketPriceMargin(offer.getMarketPriceMargin()) .withAmount(offer.getAmount().value) .withMinAmount(offer.getMinAmount().value) - .withVolume(requireNonNull(offer.getVolume()).getValue()) - .withMinVolume(requireNonNull(offer.getMinVolume()).getValue()) + .withVolume(roundedVolume) + .withMinVolume(roundedMinVolume) .withMakerFee(getMakerFee(offer, isMyOffer)) .withTxFee(offer.getTxFee().value) .withOfferFeePaymentTxId(offer.getOfferFeePaymentTxId()) @@ -206,8 +210,8 @@ public bisq.proto.grpc.OfferInfo toProtoMessage() { .setMarketPriceMargin(marketPriceMargin) .setAmount(amount) .setMinAmount(minAmount) - .setVolume(volume) - .setMinVolume(minVolume) + .setVolume(volume == null ? "0" : volume) + .setMinVolume(minVolume == null ? "0" : minVolume) .setMakerFee(makerFee) .setTxFee(txFee) .setOfferFeePaymentTxId(isBsqSwapOffer ? "" : offerFeePaymentTxId) diff --git a/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java b/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java index 1ddb5e92de0..aadffccb6db 100644 --- a/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java +++ b/core/src/main/java/bisq/core/api/model/builder/OfferInfoBuilder.java @@ -37,8 +37,8 @@ public final class OfferInfoBuilder { private double marketPriceMargin; private long amount; private long minAmount; - private long volume; - private long minVolume; + private String volume; + private String minVolume; private long txFee; private long makerFee; private String offerFeePaymentTxId; @@ -97,12 +97,12 @@ public OfferInfoBuilder withMinAmount(long minAmount) { return this; } - public OfferInfoBuilder withVolume(long volume) { + public OfferInfoBuilder withVolume(String volume) { this.volume = volume; return this; } - public OfferInfoBuilder withMinVolume(long minVolume) { + public OfferInfoBuilder withMinVolume(String minVolume) { this.minVolume = minVolume; return this; } diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 87f6609f275..3995d2de415 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -300,16 +300,12 @@ message OfferInfo { uint64 amount = 6; // The offer's minimum BTC amount in satoshis. One million satoshis is represented as 1000000. uint64 minAmount = 7; - // A long representing the rounded volume of currency to be traded for BTC. - // For EUR fiat offers, a volume of 29500.000 EUR would be represented as 29500000. - // TODO: Seems to be a bug in the volume, missing one trailing decimal. - // Price has 4 "ghost" decimal places. Volume has only 3 "ghost" decimal places, e.g., - // EUR PRICE: 295001234 - // EUR VOL: 29500000 - uint64 volume = 8; - // A long representing the minimum, rounded volume of currency to be traded for BTC. - // TODO: Resolve the problem mentioned above, in the volume field description. - uint64 minVolume = 9; + // The rounded volume of currency to be traded for BTC. + // Fiat volume is rounded to whole currency units (no cents). Altcoin volume is rounded to 2 decimal places. + string volume = 8; + // The rounded, minimum volume of currency to be traded for BTC. + // Fiat volume is rounded to whole currency units (no cents). Altcoin volume is rounded to 2 decimal places. + string minVolume = 9; // A long representing the BTC buyer's security deposit in satoshis. uint64 buyerSecurityDeposit = 10; // A market price margin based offer's trigger price is the market BTC price at which the offer is automatically disabled. From 2056e2638445f381d63631eb02403749ec91d6e6 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 16:45:37 -0300 Subject: [PATCH 15/17] Adjust cli module to grpc.proto::volume field type change (string) --- .../main/java/bisq/cli/CurrencyFormat.java | 66 ++++++++++++------- .../table/builder/AbstractTableBuilder.java | 10 +-- .../cli/table/builder/OfferTableBuilder.java | 44 ++++++++----- .../bisq/cli/table/column/AltcoinColumn.java | 1 + .../bisq/cli/table/column/FiatColumn.java | 1 + 5 files changed, 76 insertions(+), 46 deletions(-) diff --git a/cli/src/main/java/bisq/cli/CurrencyFormat.java b/cli/src/main/java/bisq/cli/CurrencyFormat.java index ba0e84fca2d..ba1029d3c72 100644 --- a/cli/src/main/java/bisq/cli/CurrencyFormat.java +++ b/cli/src/main/java/bisq/cli/CurrencyFormat.java @@ -39,8 +39,8 @@ public class CurrencyFormat { // Use the US locale for all DecimalFormat objects. private static final DecimalFormatSymbols DECIMAL_FORMAT_SYMBOLS = DecimalFormatSymbols.getInstance(Locale.US); - // Format numbers in US locale for CLI console. - private static final NumberFormat FRIENDLY_NUMBER_FORMAT = NumberFormat.getInstance(Locale.US); + // Format all numbers displayed in the CLI console with the US locale (no i18n support for CLI). + private static final NumberFormat US_LOCALE_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"); @@ -54,6 +54,9 @@ public class CurrencyFormat { static final DecimalFormat BSQ_FORMAT = new DecimalFormat("###,###,###,##0.00", DECIMAL_FORMAT_SYMBOLS); static final DecimalFormat SEND_BSQ_FORMAT = new DecimalFormat("###########0.00", DECIMAL_FORMAT_SYMBOLS); + static final DecimalFormat ALTCOIN_VOLUME_FORMAT = new DecimalFormat("########0.00", DECIMAL_FORMAT_SYMBOLS); + static final DecimalFormat FIAT_VOLUME_FORMAT = new DecimalFormat("###########0", DECIMAL_FORMAT_SYMBOLS); + static final BigDecimal SECURITY_DEPOSIT_MULTIPLICAND = new BigDecimal("0.01"); @SuppressWarnings("BigDecimalMethodWithoutRoundingCalled") @@ -71,13 +74,28 @@ public static String formatBsq(long sats) { return BSQ_FORMAT.format(BigDecimal.valueOf(sats).divide(BSQ_SATOSHI_DIVISOR)); } + @Deprecated // TODO delete public static String formatBsqAmount(long bsqSats) { - FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(2); - FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(2); - FRIENDLY_NUMBER_FORMAT.setRoundingMode(HALF_UP); + US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(2); + US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(2); + US_LOCALE_NUMBER_FORMAT.setRoundingMode(HALF_UP); return SEND_BSQ_FORMAT.format((double) bsqSats / SATOSHI_DIVISOR.doubleValue()); } + public static String formatVolumeString(String volumeString, int precision) { + if (volumeString == null || volumeString.isBlank()) + return ""; + + US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(precision); + US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(precision); + US_LOCALE_NUMBER_FORMAT.setRoundingMode(HALF_UP); + var volAsDouble = new BigDecimal(volumeString).doubleValue(); + if (precision == 0) + return FIAT_VOLUME_FORMAT.format(volAsDouble); + else + return ALTCOIN_VOLUME_FORMAT.format(volAsDouble); + } + public static String formatTxFeeRateInfo(TxFeeRateInfo txFeeRateInfo) { if (txFeeRateInfo.getUseCustomTxFeeRate()) return format("custom tx fee rate: %s sats/byte, network rate: %s sats/byte, min network rate: %s sats/byte", @@ -118,31 +136,31 @@ public static String formatInternalFiatPrice(BigDecimal price) { } public static String formatInternalFiatPrice(double price) { - FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(4); - FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(4); - return FRIENDLY_NUMBER_FORMAT.format(price); + US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(4); + US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(4); + return US_LOCALE_NUMBER_FORMAT.format(price); } @Deprecated public static String formatPrice(long price) { - FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(4); - FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(4); - FRIENDLY_NUMBER_FORMAT.setRoundingMode(UNNECESSARY); - return FRIENDLY_NUMBER_FORMAT.format((double) price / 10_000); + US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(4); + US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(4); + US_LOCALE_NUMBER_FORMAT.setRoundingMode(UNNECESSARY); + return US_LOCALE_NUMBER_FORMAT.format((double) price / 10_000); } public static String formatCryptoCurrencyPrice(long price) { - FRIENDLY_NUMBER_FORMAT.setMinimumFractionDigits(8); - FRIENDLY_NUMBER_FORMAT.setMaximumFractionDigits(8); - FRIENDLY_NUMBER_FORMAT.setRoundingMode(UNNECESSARY); - return FRIENDLY_NUMBER_FORMAT.format((double) price / SATOSHI_DIVISOR.doubleValue()); + US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(8); + US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(8); + US_LOCALE_NUMBER_FORMAT.setRoundingMode(UNNECESSARY); + return US_LOCALE_NUMBER_FORMAT.format((double) price / SATOSHI_DIVISOR.doubleValue()); } 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); + US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(0); + US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(0); + US_LOCALE_NUMBER_FORMAT.setRoundingMode(HALF_UP); + return US_LOCALE_NUMBER_FORMAT.format((double) volume / 10_000); } public static String formatCryptoCurrencyVolume(long volume) { @@ -151,10 +169,10 @@ public static String formatCryptoCurrencyVolume(long volume) { } 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()); + US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(precision); + US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(precision); + US_LOCALE_NUMBER_FORMAT.setRoundingMode(HALF_UP); + return US_LOCALE_NUMBER_FORMAT.format((double) volume / SATOSHI_DIVISOR.doubleValue()); } @Deprecated diff --git a/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java b/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java index cdb5f3ffa3f..1b57fa691c8 100644 --- a/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java +++ b/cli/src/main/java/bisq/cli/table/builder/AbstractTableBuilder.java @@ -20,7 +20,6 @@ import bisq.proto.grpc.OfferInfo; import java.util.List; -import java.util.function.Function; import java.util.function.Predicate; @@ -32,7 +31,7 @@ */ abstract class AbstractTableBuilder { - protected final Function toBlankOrNonZeroValue = (s) -> s.trim().equals("0") ? "" : s; + protected final Predicate isFiatOffer = (o) -> o.getBaseCurrencyCode().equals("BTC"); protected final TableType tableType; protected final List protos; @@ -45,6 +44,9 @@ abstract class AbstractTableBuilder { } public abstract Table build(); - - protected final Predicate isFiatOffer = (o) -> o.getBaseCurrencyCode().equals("BTC"); } + +/* + var currencyCode = isFiatOffer.test(o); + + */ diff --git a/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java b/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java index a97c73b848e..5a86ce92a79 100644 --- a/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java +++ b/cli/src/main/java/bisq/cli/table/builder/OfferTableBuilder.java @@ -26,13 +26,12 @@ import javax.annotation.Nullable; +import static bisq.cli.CurrencyFormat.formatVolumeString; import static bisq.cli.table.builder.TableBuilderConstants.*; import static bisq.cli.table.builder.TableType.OFFER_TBL; -import static bisq.cli.table.column.AltcoinColumn.DISPLAY_MODE.ALTCOIN_OFFER_VOLUME; import static bisq.cli.table.column.Column.JUSTIFICATION.LEFT; import static bisq.cli.table.column.Column.JUSTIFICATION.NONE; import static bisq.cli.table.column.Column.JUSTIFICATION.RIGHT; -import static bisq.cli.table.column.FiatColumn.DISPLAY_MODE.VOLUME; import static bisq.cli.table.column.ZippedStringColumns.DUPLICATION_MODE.EXCLUDE_DUPLICATES; import static java.lang.String.format; import static protobuf.OfferDirection.BUY; @@ -41,9 +40,7 @@ import bisq.cli.table.Table; -import bisq.cli.table.column.AltcoinColumn; import bisq.cli.table.column.Column; -import bisq.cli.table.column.FiatColumn; import bisq.cli.table.column.Iso8601DateTimeColumn; import bisq.cli.table.column.SatoshiColumn; import bisq.cli.table.column.StringColumn; @@ -79,8 +76,8 @@ public Table buildFiatOfferTable(List offers) { @Nullable Column colEnabled = enabledColumn.get(); // Not boolean: YES, NO, or PENDING Column colFiatPrice = new StringColumn(format(COL_HEADER_DETAILED_PRICE, fiatTradeCurrency.get()), RIGHT); - Column colFiatVolume = new FiatColumn(format("Temp Volume (%s)", fiatTradeCurrency.get()), NONE, VOLUME); - Column colMinFiatVolume = new FiatColumn(format("Temp Min Volume (%s)", fiatTradeCurrency.get()), NONE, VOLUME); + Column colFiatVolume = new StringColumn(format("Temp Volume (%s)", fiatTradeCurrency.get()), NONE); + Column colMinFiatVolume = new StringColumn(format("Temp Min Volume (%s)", fiatTradeCurrency.get()), NONE); @Nullable Column colTriggerPrice = fiatTriggerPriceColumn.get(); @@ -95,8 +92,10 @@ public Table buildFiatOfferTable(List offers) { colFiatPrice.addRow(o.getPrice()); colMinAmount.addRow(o.getMinAmount()); colAmount.addRow(o.getAmount()); - colMinFiatVolume.addRow(o.getMinVolume()); - colFiatVolume.addRow(o.getVolume()); + + var volumePrecision = toOfferVolumePrecision.apply(o); + colMinFiatVolume.addRow(formatVolumeString(toBlankOrNonZeroValue.apply(o.getMinVolume()), volumePrecision)); + colFiatVolume.addRow(formatVolumeString(o.getVolume(), volumePrecision)); if (colTriggerPrice != null) colTriggerPrice.addRow(toBlankOrNonZeroValue.apply(o.getTriggerPrice())); @@ -142,12 +141,8 @@ public Table buildCryptoCurrencyOfferTable(List offers) { @Nullable Column colEnabled = enabledColumn.get(); // Not boolean: YES, NO, or PENDING Column colBtcPrice = new StringColumn(format(COL_HEADER_DETAILED_PRICE_OF_ALTCOIN, altcoinTradeCurrency.get()), RIGHT); - Column colBtcVolume = new AltcoinColumn(format("Temp Volume (%s)", altcoinTradeCurrency.get()), - NONE, - ALTCOIN_OFFER_VOLUME); - Column colMinBtcVolume = new AltcoinColumn(format("Temp Min Volume (%s)", altcoinTradeCurrency.get()), - NONE, - ALTCOIN_OFFER_VOLUME); + Column colBtcVolume = new StringColumn(format("Temp Volume (%s)", altcoinTradeCurrency.get()), NONE); + Column colMinBtcVolume = new StringColumn(format("Temp Min Volume (%s)", altcoinTradeCurrency.get()), NONE); @Nullable Column colTriggerPrice = altcoinTriggerPriceColumn.get(); @@ -162,8 +157,9 @@ public Table buildCryptoCurrencyOfferTable(List offers) { colBtcPrice.addRow(o.getPrice()); colAmount.addRow(o.getAmount()); colMinAmount.addRow(o.getMinAmount()); - colBtcVolume.addRow(o.getMinVolume()); - colMinBtcVolume.addRow(o.getVolume()); + var volumePrecision = toOfferVolumePrecision.apply(o); + colBtcVolume.addRow(formatVolumeString(o.getVolume(), volumePrecision)); + colMinBtcVolume.addRow(formatVolumeString(toBlankOrNonZeroValue.apply(o.getMinVolume()), volumePrecision)); if (colTriggerPrice != null) colTriggerPrice.addRow(toBlankOrNonZeroValue.apply(o.getTriggerPrice())); @@ -178,8 +174,8 @@ public Table buildCryptoCurrencyOfferTable(List offers) { new ZippedStringColumns(format(COL_HEADER_VOLUME_RANGE, altcoinTradeCurrency.get()), RIGHT, " - ", - colBtcVolume.asStringColumn(), - colMinBtcVolume.asStringColumn()); + colMinBtcVolume.asStringColumn(), + colBtcVolume.asStringColumn()); // Define and return the table instance with populated columns. @@ -215,6 +211,18 @@ public Table buildCryptoCurrencyOfferTable(List offers) { } } + // TODO Might want to move these three functions into superclass (if TradeTableBuilder needs them). + private final Function toBlankOrNonZeroValue = (s) -> s.trim().equals("0") ? "" : s; + private final Function toOfferCurrencyCode = (o) -> isFiatOffer.test(o) + ? o.getCounterCurrencyCode() + : o.getBaseCurrencyCode(); + private final Function toOfferVolumePrecision = (o) -> { + if (isFiatOffer.test(o)) + return 0; + else + return toOfferCurrencyCode.apply(o).equals("BSQ") ? 2 : 8; + }; + private final Supplier firstOfferInList = () -> (OfferInfo) protos.get(0); private final Supplier isShowingMyOffers = () -> firstOfferInList.get().getIsMyOffer(); private final Supplier isShowingFiatOffers = () -> isFiatOffer.test(firstOfferInList.get()); diff --git a/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java b/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java index 3b13171f7f7..79f4976bf5b 100644 --- a/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java +++ b/cli/src/main/java/bisq/cli/table/column/AltcoinColumn.java @@ -32,6 +32,7 @@ public class AltcoinColumn extends LongColumn { public enum DISPLAY_MODE { + @Deprecated ALTCOIN_OFFER_VOLUME, ALTCOIN_PRICE, @Deprecated diff --git a/cli/src/main/java/bisq/cli/table/column/FiatColumn.java b/cli/src/main/java/bisq/cli/table/column/FiatColumn.java index 9adb9de5a01..81ebcb7fe58 100644 --- a/cli/src/main/java/bisq/cli/table/column/FiatColumn.java +++ b/cli/src/main/java/bisq/cli/table/column/FiatColumn.java @@ -35,6 +35,7 @@ public enum DISPLAY_MODE { PRICE, @Deprecated TRIGGER_PRICE, + @Deprecated VOLUME } From 31c8fbb679b9574f3ec82a201161701add59e3b0 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 16:48:32 -0300 Subject: [PATCH 16/17] Remove some dead code --- .../main/java/bisq/cli/CurrencyFormat.java | 30 ------------------- 1 file changed, 30 deletions(-) diff --git a/cli/src/main/java/bisq/cli/CurrencyFormat.java b/cli/src/main/java/bisq/cli/CurrencyFormat.java index ba1029d3c72..403e5544ca7 100644 --- a/cli/src/main/java/bisq/cli/CurrencyFormat.java +++ b/cli/src/main/java/bisq/cli/CurrencyFormat.java @@ -52,7 +52,6 @@ public class CurrencyFormat { static final BigDecimal BSQ_SATOSHI_DIVISOR = new BigDecimal(100); static final DecimalFormat BSQ_FORMAT = new DecimalFormat("###,###,###,##0.00", DECIMAL_FORMAT_SYMBOLS); - static final DecimalFormat SEND_BSQ_FORMAT = new DecimalFormat("###########0.00", DECIMAL_FORMAT_SYMBOLS); static final DecimalFormat ALTCOIN_VOLUME_FORMAT = new DecimalFormat("########0.00", DECIMAL_FORMAT_SYMBOLS); static final DecimalFormat FIAT_VOLUME_FORMAT = new DecimalFormat("###########0", DECIMAL_FORMAT_SYMBOLS); @@ -74,14 +73,6 @@ public static String formatBsq(long sats) { return BSQ_FORMAT.format(BigDecimal.valueOf(sats).divide(BSQ_SATOSHI_DIVISOR)); } - @Deprecated // TODO delete - public static String formatBsqAmount(long bsqSats) { - US_LOCALE_NUMBER_FORMAT.setMinimumFractionDigits(2); - US_LOCALE_NUMBER_FORMAT.setMaximumFractionDigits(2); - US_LOCALE_NUMBER_FORMAT.setRoundingMode(HALF_UP); - return SEND_BSQ_FORMAT.format((double) bsqSats / SATOSHI_DIVISOR.doubleValue()); - } - public static String formatVolumeString(String volumeString, int precision) { if (volumeString == null || volumeString.isBlank()) return ""; @@ -108,27 +99,6 @@ public static String formatTxFeeRateInfo(TxFeeRateInfo txFeeRateInfo) { 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 - ? formatFiatVolume(minVolume) + " - " + formatFiatVolume(volume) - : formatFiatVolume(volume); - } - - @Deprecated - public static String formatCryptoCurrencyVolumeRange(long minVolume, long volume) { - return minVolume != volume - ? formatCryptoCurrencyVolume(minVolume) + " - " + formatCryptoCurrencyVolume(volume) - : formatCryptoCurrencyVolume(volume); - } - public static String formatInternalFiatPrice(BigDecimal price) { INTERNAL_FIAT_DECIMAL_FORMAT.setMinimumFractionDigits(4); INTERNAL_FIAT_DECIMAL_FORMAT.setMaximumFractionDigits(4); From 15f75eea3d1d0dda0a586e7c07496960294c8b04 Mon Sep 17 00:00:00 2001 From: ghubstan <36207203+ghubstan@users.noreply.github.com> Date: Fri, 18 Feb 2022 16:49:51 -0300 Subject: [PATCH 17/17] Add some asserts on volume/min-volume strings from server --- .../method/offer/CreateBSQOffersTest.java | 28 +++++++++++++++---- .../offer/CreateOfferUsingFixedPriceTest.java | 18 ++++++++++-- ...CreateOfferUsingMarketPriceMarginTest.java | 10 +++---- .../method/trade/AbstractTradeTest.java | 12 +++++--- .../method/trade/TakeBuyBSQOfferTest.java | 2 +- .../method/trade/TakeSellBSQOfferTest.java | 2 +- 6 files changed, 52 insertions(+), 20 deletions(-) diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java index 57b318e68ed..2b878c1803d 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateBSQOffersTest.java @@ -66,7 +66,7 @@ public void testCreateBuy1BTCFor20KBSQOffer() { getDefaultBuyerSecurityDepositAsPercent(), alicesLegacyBsqAcct.getId(), MAKER_FEE_CURRENCY_CODE); - log.debug("Sell BSQ (Buy BTC) OFFER:\n{}", toOfferTable.apply(newOffer)); + log.debug("Sell BSQ (Buy BTC) Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -77,6 +77,8 @@ public void testCreateBuy1BTCFor20KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); + assertEquals("20000.00", newOffer.getVolume()); + assertEquals("20000.00", newOffer.getMinVolume()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -94,6 +96,8 @@ public void testCreateBuy1BTCFor20KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); + assertEquals("20000.00", newOffer.getVolume()); + assertEquals("20000.00", newOffer.getMinVolume()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -113,7 +117,7 @@ public void testCreateSell1BTCFor20KBSQOffer() { getDefaultBuyerSecurityDepositAsPercent(), alicesLegacyBsqAcct.getId(), MAKER_FEE_CURRENCY_CODE); - log.debug("SELL 20K BSQ OFFER:\n{}", toOfferTable.apply(newOffer)); + log.debug("SELL 20K BSQ Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -124,6 +128,8 @@ public void testCreateSell1BTCFor20KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); + assertEquals("20000.00", newOffer.getVolume()); + assertEquals("20000.00", newOffer.getMinVolume()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -141,6 +147,8 @@ public void testCreateSell1BTCFor20KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(100_000_000L, newOffer.getAmount()); assertEquals(100_000_000L, newOffer.getMinAmount()); + assertEquals("20000.00", newOffer.getVolume()); + assertEquals("20000.00", newOffer.getMinVolume()); assertEquals(15_000_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -160,7 +168,7 @@ public void testCreateBuyBTCWith1To2KBSQOffer() { getDefaultBuyerSecurityDepositAsPercent(), alicesLegacyBsqAcct.getId(), MAKER_FEE_CURRENCY_CODE); - log.debug("BUY 1-2K BSQ OFFER:\n{}", toOfferTable.apply(newOffer)); + log.debug("BUY 1-2K BSQ Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -171,6 +179,8 @@ public void testCreateBuyBTCWith1To2KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(10_000_000L, newOffer.getAmount()); assertEquals(5_000_000L, newOffer.getMinAmount()); + assertEquals("2000.00", newOffer.getVolume()); + assertEquals("1000.00", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -188,6 +198,8 @@ public void testCreateBuyBTCWith1To2KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(10_000_000L, newOffer.getAmount()); assertEquals(5_000_000L, newOffer.getMinAmount()); + assertEquals("2000.00", newOffer.getVolume()); + assertEquals("1000.00", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -207,7 +219,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() { getDefaultBuyerSecurityDepositAsPercent(), alicesLegacyBsqAcct.getId(), MAKER_FEE_CURRENCY_CODE); - log.debug("SELL 5-10K BSQ OFFER:\n{}", toOfferTable.apply(newOffer)); + log.debug("SELL 5-10K BSQ Offer:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -218,6 +230,8 @@ public void testCreateSellBTCFor5To10KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(50_000_000L, newOffer.getAmount()); assertEquals(25_000_000L, newOffer.getMinAmount()); + assertEquals("10000.00", newOffer.getVolume()); + assertEquals("5000.00", newOffer.getMinVolume()); assertEquals(7_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -235,6 +249,8 @@ public void testCreateSellBTCFor5To10KBSQOffer() { assertEquals("0.00005000", newOffer.getPrice()); assertEquals(50_000_000L, newOffer.getAmount()); assertEquals(25_000_000L, newOffer.getMinAmount()); + assertEquals("10000.00", newOffer.getVolume()); + assertEquals("5000.00", newOffer.getMinVolume()); assertEquals(7_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(alicesLegacyBsqAcct.getId(), newOffer.getPaymentAccountId()); assertEquals(BSQ, newOffer.getBaseCurrencyCode()); @@ -246,7 +262,7 @@ public void testCreateSellBTCFor5To10KBSQOffer() { @Order(5) public void testGetAllMyBsqOffers() { List offers = aliceClient.getMyCryptoCurrencyOffersSortedByDate(BSQ); - log.debug("ALL ALICE'S BSQ OFFERS:\n{}", toOffersTable.apply(offers)); + log.debug("All Alice's BSQ Offers:\n{}", toOffersTable.apply(offers)); assertEquals(4, offers.size()); log.debug("ALICE'S BALANCES\n{}", formatBalancesTbls(aliceClient.getBalances())); } @@ -255,7 +271,7 @@ public void testGetAllMyBsqOffers() { @Order(6) public void testGetAvailableBsqOffers() { List offers = bobClient.getCryptoCurrencyOffersSortedByDate(BSQ); - log.debug("ALL BOB'S AVAILABLE BSQ OFFERS:\n{}", toOffersTable.apply(offers)); + log.debug("All Bob's Available BSQ Offers:\n{}", toOffersTable.apply(offers)); assertEquals(4, offers.size()); log.debug("BOB'S BALANCES\n{}", formatBalancesTbls(bobClient.getBalances())); } diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java index fb921a2cbdd..794fb1310a8 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingFixedPriceTest.java @@ -58,7 +58,7 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { getDefaultBuyerSecurityDepositAsPercent(), audAccount.getId(), MAKER_FEE_CURRENCY_CODE); - log.debug("OFFER #1:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #1:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -69,6 +69,8 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { assertEquals("36000.0000", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); + assertEquals("3600", newOffer.getVolume()); + assertEquals("3600", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(audAccount.getId(), newOffer.getPaymentAccountId()); assertEquals(BTC, newOffer.getBaseCurrencyCode()); @@ -84,6 +86,8 @@ public void testCreateAUDBTCBuyOfferUsingFixedPrice16000() { assertEquals("36000.0000", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); + assertEquals("3600", newOffer.getVolume()); + assertEquals("3600", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(audAccount.getId(), newOffer.getPaymentAccountId()); assertEquals(BTC, newOffer.getBaseCurrencyCode()); @@ -103,7 +107,7 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { getDefaultBuyerSecurityDepositAsPercent(), usdAccount.getId(), MAKER_FEE_CURRENCY_CODE); - log.debug("OFFER #2:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #2:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -114,6 +118,8 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { assertEquals("30000.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); + assertEquals("3000", newOffer.getVolume()); + assertEquals("3000", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(usdAccount.getId(), newOffer.getPaymentAccountId()); assertEquals(BTC, newOffer.getBaseCurrencyCode()); @@ -129,6 +135,8 @@ public void testCreateUSDBTCBuyOfferUsingFixedPrice100001234() { assertEquals("30000.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(10_000_000, newOffer.getMinAmount()); + assertEquals("3000", newOffer.getVolume()); + assertEquals("3000", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(usdAccount.getId(), newOffer.getPaymentAccountId()); assertEquals(BTC, newOffer.getBaseCurrencyCode()); @@ -148,7 +156,7 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { getDefaultBuyerSecurityDepositAsPercent(), eurAccount.getId(), MAKER_FEE_CURRENCY_CODE); - log.debug("OFFER #3:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #3:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -159,6 +167,8 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { assertEquals("29500.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(5_000_000, newOffer.getMinAmount()); + assertEquals("2950", newOffer.getVolume()); + assertEquals("1475", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(eurAccount.getId(), newOffer.getPaymentAccountId()); assertEquals(BTC, newOffer.getBaseCurrencyCode()); @@ -174,6 +184,8 @@ public void testCreateEURBTCSellOfferUsingFixedPrice95001234() { assertEquals("29500.1234", newOffer.getPrice()); assertEquals(10_000_000, newOffer.getAmount()); assertEquals(5_000_000, newOffer.getMinAmount()); + assertEquals("2950", newOffer.getVolume()); + assertEquals("1475", newOffer.getMinVolume()); assertEquals(1_500_000, newOffer.getBuyerSecurityDeposit()); assertEquals(eurAccount.getId(), newOffer.getPaymentAccountId()); assertEquals(BTC, newOffer.getBaseCurrencyCode()); diff --git a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java index 2dd32d44d3d..7ad241f50c0 100644 --- a/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java +++ b/apitest/src/test/java/bisq/apitest/method/offer/CreateOfferUsingMarketPriceMarginTest.java @@ -75,7 +75,7 @@ public void testCreateUSDBTCBuyOffer5PctPriceMargin() { usdAccount.getId(), MAKER_FEE_CURRENCY_CODE, NO_TRIGGER_PRICE); - log.debug("OFFER #1:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #1:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -122,7 +122,7 @@ public void testCreateNZDBTCBuyOfferMinus2PctPriceMargin() { nzdAccount.getId(), MAKER_FEE_CURRENCY_CODE, NO_TRIGGER_PRICE); - log.debug("OFFER #2:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #2:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -169,7 +169,7 @@ public void testCreateGBPBTCSellOfferMinus1Point5PctPriceMargin() { gbpAccount.getId(), MAKER_FEE_CURRENCY_CODE, NO_TRIGGER_PRICE); - log.debug("OFFER #3:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #3:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -216,7 +216,7 @@ public void testCreateBRLBTCSellOffer6Point55PctPriceMargin() { brlAccount.getId(), MAKER_FEE_CURRENCY_CODE, NO_TRIGGER_PRICE); - log.debug("OFFER #4:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #4:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertTrue(newOffer.getIsMyPendingOffer()); @@ -269,7 +269,7 @@ public void testCreateUSDBTCBuyOfferWithTriggerPrice() { genBtcBlocksThenWait(1, 4000); // give time to add to offer book newOffer = aliceClient.getOffer(newOffer.getId()); - log.debug("OFFER #5:\n{}", toOfferTable.apply(newOffer)); + log.debug("Offer #5:\n{}", toOfferTable.apply(newOffer)); assertTrue(newOffer.getIsMyOffer()); assertFalse(newOffer.getIsMyPendingOffer()); assertEquals(triggerPrice, newOffer.getTriggerPrice()); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java index 5ceebe026a2..5ea52777c63 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/AbstractTradeTest.java @@ -14,7 +14,6 @@ import org.junit.jupiter.api.TestInfo; import static bisq.apitest.config.ApiTestConfig.BTC; -import static bisq.cli.CurrencyFormat.formatBsqAmount; import static bisq.cli.table.builder.TableType.TRADE_DETAIL_TBL; import static bisq.core.trade.model.bisq_v1.Trade.Phase.DEPOSIT_CONFIRMED; import static bisq.core.trade.model.bisq_v1.Trade.Phase.FIAT_SENT; @@ -208,7 +207,10 @@ protected final void sendBsqPayment(Logger log, String receiverAddress = contract.getIsBuyerMakerAndSellerTaker() ? contract.getTakerPaymentAccountPayload().getAddress() : contract.getMakerPaymentAccountPayload().getAddress(); - String sendBsqAmount = formatBsqAmount(trade.getOffer().getVolume()); + // TODO Fix trade vol src bug for subclasses. + // This bug was fixed for production CLI with https://github.com/bisq-network/bisq/pull/5704 on Sep 27, 2021 + String sendBsqAmount = trade.getOffer().getVolume(); + // String sendBsqAmount = trade.getTradeVolume(); log.debug("Sending {} BSQ to address {}", sendBsqAmount, receiverAddress); grpcClient.sendBsq(receiverAddress, sendBsqAmount, ""); } @@ -217,8 +219,10 @@ protected final void verifyBsqPaymentHasBeenReceived(Logger log, GrpcClient grpcClient, TradeInfo trade) { var contract = trade.getContract(); - var bsqSats = trade.getOffer().getVolume(); - var receiveAmountAsString = formatBsqAmount(bsqSats); + // TODO Fix trade vol src bug for subclasses. + // This bug was fixed for production with https://github.com/bisq-network/bisq/pull/5704 on Sep 27, 2021 + var receiveAmountAsString = trade.getOffer().getVolume(); + // String receiveAmountAsString = trade.getTradeVolume(); var address = contract.getIsBuyerMakerAndSellerTaker() ? contract.getTakerPaymentAccountPayload().getAddress() : contract.getMakerPaymentAccountPayload().getAddress(); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java index 6a37a3d1217..50bde49e244 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeBuyBSQOfferTest.java @@ -79,7 +79,7 @@ public void testTakeAlicesSellBTCForBSQOffer(final TestInfo testInfo) { getDefaultBuyerSecurityDepositAsPercent(), alicesLegacyBsqAcct.getId(), TRADE_FEE_CURRENCY_CODE); - log.debug("ALICE'S BUY BSQ (SELL BTC) OFFER:\n{}", toOfferTable.apply(alicesOffer)); + log.debug("Alice's BUY BSQ (SELL BTC) Offer:\n{}", toOfferTable.apply(alicesOffer)); genBtcBlocksThenWait(1, 5000); var offerId = alicesOffer.getId(); assertFalse(alicesOffer.getIsCurrencyForMakerFeeBtc()); diff --git a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java index f4411c51789..ac1f0569153 100644 --- a/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java +++ b/apitest/src/test/java/bisq/apitest/method/trade/TakeSellBSQOfferTest.java @@ -81,7 +81,7 @@ public void testTakeAlicesBuyBTCForBSQOffer(final TestInfo testInfo) { getDefaultBuyerSecurityDepositAsPercent(), alicesLegacyBsqAcct.getId(), TRADE_FEE_CURRENCY_CODE); - log.debug("ALICE'S SELL BSQ (BUY BTC) OFFER:\n{}", new TableBuilder(OFFER_TBL, alicesOffer).build()); + log.debug("Alice's SELL BSQ (BUY BTC) Offer:\n{}", new TableBuilder(OFFER_TBL, alicesOffer).build()); genBtcBlocksThenWait(1, 4_000); var offerId = alicesOffer.getId(); assertTrue(alicesOffer.getIsCurrencyForMakerFeeBtc());