diff --git a/cli/src/main/java/haveno/cli/CliMain.java b/cli/src/main/java/haveno/cli/CliMain.java index 58dcce46314..e028e20fc76 100644 --- a/cli/src/main/java/haveno/cli/CliMain.java +++ b/cli/src/main/java/haveno/cli/CliMain.java @@ -22,17 +22,19 @@ import haveno.cli.opts.CreateCryptoCurrencyPaymentAcctOptionParser; import haveno.cli.opts.CreateOfferOptionParser; import haveno.cli.opts.CreatePaymentAcctOptionParser; +import haveno.cli.opts.CreateXmrTxOptionParser; import haveno.cli.opts.GetAddressBalanceOptionParser; -import haveno.cli.opts.GetBTCMarketPriceOptionParser; import haveno.cli.opts.GetBalanceOptionParser; +import haveno.cli.opts.GetMarketPriceOptionParser; import haveno.cli.opts.GetOffersOptionParser; import haveno.cli.opts.GetPaymentAcctFormOptionParser; import haveno.cli.opts.GetTradeOptionParser; import haveno.cli.opts.GetTradesOptionParser; import haveno.cli.opts.OfferIdOptionParser; +import haveno.cli.opts.OptLabel; import haveno.cli.opts.RegisterDisputeAgentOptionParser; +import haveno.cli.opts.RelayXmrTxsOptionParser; import haveno.cli.opts.RemoveWalletPasswordOptionParser; -import haveno.cli.opts.SendBtcOptionParser; import haveno.cli.opts.SetWalletPasswordOptionParser; import haveno.cli.opts.SimpleMethodOptionParser; import haveno.cli.opts.TakeOfferOptionParser; @@ -40,6 +42,8 @@ import haveno.cli.opts.WithdrawFundsOptionParser; import haveno.cli.table.builder.TableBuilder; import haveno.proto.grpc.OfferInfo; +import haveno.proto.grpc.XmrDestination; +import haveno.proto.grpc.GetTradesRequest; import io.grpc.StatusRuntimeException; import joptsimple.OptionParser; import joptsimple.OptionSet; @@ -56,58 +60,66 @@ import java.util.Date; import java.util.List; -import static haveno.cli.CurrencyFormat.formatInternalFiatPrice; -import static haveno.cli.CurrencyFormat.toSatoshis; -import static haveno.cli.Method.canceloffer; -import static haveno.cli.Method.closetrade; -import static haveno.cli.Method.confirmpaymentreceived; -import static haveno.cli.Method.confirmpaymentsent; -import static haveno.cli.Method.createcryptopaymentacct; -import static haveno.cli.Method.createoffer; -import static haveno.cli.Method.createpaymentacct; -import static haveno.cli.Method.editoffer; -import static haveno.cli.Method.failtrade; -import static haveno.cli.Method.getaddressbalance; +import static haveno.cli.Method.getversion; import static haveno.cli.Method.getbalance; -import static haveno.cli.Method.getbtcprice; +import static haveno.cli.Method.getaddressbalance; +import static haveno.cli.Method.getxmrprice; import static haveno.cli.Method.getfundingaddresses; -import static haveno.cli.Method.getmyoffer; -import static haveno.cli.Method.getmyoffers; +import static haveno.cli.Method.getunusedxmraddress; +import static haveno.cli.Method.getxmrseed; +import static haveno.cli.Method.getxmrprimaryaddress; +import static haveno.cli.Method.getxmrnewsubaddress; +import static haveno.cli.Method.getxmrtxs; +import static haveno.cli.Method.createxmrtx; +import static haveno.cli.Method.relayxmrtxs; +import static haveno.cli.Method.createoffer; +import static haveno.cli.Method.canceloffer; import static haveno.cli.Method.getoffer; +import static haveno.cli.Method.getmyoffer; import static haveno.cli.Method.getoffers; -import static haveno.cli.Method.getpaymentacctform; -import static haveno.cli.Method.getpaymentaccts; -import static haveno.cli.Method.getpaymentmethods; +import static haveno.cli.Method.getmyoffers; +import static haveno.cli.Method.takeoffer; import static haveno.cli.Method.gettrade; import static haveno.cli.Method.gettrades; -import static haveno.cli.Method.gettransaction; -import static haveno.cli.Method.gettxfeerate; -import static haveno.cli.Method.getunusedbsqaddress; -import static haveno.cli.Method.getversion; +import static haveno.cli.Method.confirmpaymentsent; +import static haveno.cli.Method.confirmpaymentreceived; +import static haveno.cli.Method.withdrawfunds; +import static haveno.cli.Method.getpaymentmethods; +import static haveno.cli.Method.getpaymentacctform; +import static haveno.cli.Method.createpaymentacct; +import static haveno.cli.Method.createcryptopaymentacct; +import static haveno.cli.Method.getpaymentaccts; import static haveno.cli.Method.lockwallet; -import static haveno.cli.Method.sendbtc; -import static haveno.cli.Method.settxfeerate; +import static haveno.cli.Method.unlockwallet; +import static haveno.cli.Method.removewalletpassword; import static haveno.cli.Method.setwalletpassword; +import static haveno.cli.Method.registerdisputeagent; import static haveno.cli.Method.stop; -import static haveno.cli.Method.takeoffer; -import static haveno.cli.Method.unfailtrade; -import static haveno.cli.Method.unlockwallet; -import static haveno.cli.Method.unsettxfeerate; -import static haveno.cli.Method.withdrawfunds; -import static haveno.cli.opts.OptLabel.OPT_AMOUNT; import static haveno.cli.opts.OptLabel.OPT_HELP; import static haveno.cli.opts.OptLabel.OPT_HOST; -import static haveno.cli.opts.OptLabel.OPT_PASSWORD; import static haveno.cli.opts.OptLabel.OPT_PORT; -import static haveno.cli.opts.OptLabel.OPT_TX_FEE_RATE; +import static haveno.cli.opts.OptLabel.OPT_PASSWORD; +import static haveno.cli.table.builder.TableType.XMR_BALANCE_TBL; import static haveno.cli.table.builder.TableType.ADDRESS_BALANCE_TBL; -import static haveno.cli.table.builder.TableType.BTC_BALANCE_TBL; -import static haveno.cli.table.builder.TableType.CLOSED_TRADES_TBL; -import static haveno.cli.table.builder.TableType.FAILED_TRADES_TBL; import static haveno.cli.table.builder.TableType.OFFER_TBL; +import static haveno.cli.table.builder.TableType.TRADE_DETAIL_TBL; import static haveno.cli.table.builder.TableType.OPEN_TRADES_TBL; +import static haveno.cli.table.builder.TableType.CLOSED_TRADES_TBL; +import static haveno.cli.table.builder.TableType.FAILED_TRADES_TBL; import static haveno.cli.table.builder.TableType.PAYMENT_ACCOUNT_TBL; -import static haveno.cli.table.builder.TableType.TRADE_DETAIL_TBL; +import static haveno.cli.CurrencyFormat.formatInternalFiatPrice; +import static haveno.cli.CurrencyFormat.toPiconeros; +import static haveno.proto.grpc.GetTradesRequest.Category.CLOSED; +import static haveno.proto.grpc.GetTradesRequest.Category.OPEN; +import static java.lang.String.format; +import static java.lang.System.err; +import static java.lang.System.exit; +import static java.lang.System.out; +import static haveno.cli.CurrencyFormat.formatInternalFiatPrice; +import static haveno.cli.CurrencyFormat.toPiconeros; +import static haveno.cli.Method.*; +import static haveno.cli.opts.OptLabel.*; +import static haveno.cli.table.builder.TableType.*; import static haveno.proto.grpc.GetTradesRequest.Category.CLOSED; import static haveno.proto.grpc.GetTradesRequest.Category.OPEN; import static java.lang.String.format; @@ -131,21 +143,21 @@ public static void main(String[] args) { } public static void run(String[] args) { - var parser = new OptionParser(); + OptionParser parser = new OptionParser(); - var helpOpt = parser.accepts(OPT_HELP, "Print this help text") + parser.accepts(OPT_HELP, "Print this help text") .forHelp(); - var hostOpt = parser.accepts(OPT_HOST, "rpc server hostname or ip") + parser.accepts(OPT_HOST, "rpc server hostname or ip") .withRequiredArg() .defaultsTo("localhost"); - var portOpt = parser.accepts(OPT_PORT, "rpc server port") + parser.accepts(OPT_PORT, "rpc server port") .withRequiredArg() .ofType(Integer.class) .defaultsTo(9998); - var passwordOpt = parser.accepts(OPT_PASSWORD, "rpc server password") + parser.accepts(OPT_PASSWORD, "rpc server password") .withRequiredArg(); // Parse the CLI opts host, port, password, method name, and help. The help opt @@ -153,32 +165,32 @@ public static void run(String[] args) { // from the parsed options if a method opt is present in String[] args. OptionSet options = parser.parse(new ArgumentList(args).getCLIArguments()); @SuppressWarnings("unchecked") - var nonOptionArgs = (List) options.nonOptionArguments(); + List nonOptionArgs = (List) options.nonOptionArguments(); // If neither the help opt nor a method name is present, print CLI level help // to stderr and throw an exception. - if (!options.has(helpOpt) && nonOptionArgs.isEmpty()) { + if (!options.has(OPT_HELP) && nonOptionArgs.isEmpty()) { printHelp(parser, err); throw new IllegalArgumentException("no method specified"); } // If the help opt is present, but not a method name, print CLI level help // to stdout. - if (options.has(helpOpt) && nonOptionArgs.isEmpty()) { + if (options.has(OPT_HELP) && nonOptionArgs.isEmpty()) { printHelp(parser, out); return; } - var host = options.valueOf(hostOpt); - var port = options.valueOf(portOpt); - var password = options.valueOf(passwordOpt); + String host = (String) options.valueOf(OPT_HOST); + int port = (Integer) options.valueOf(OPT_PORT); + String password = (String) options.valueOf(OPT_PASSWORD); if (password == null) throw new IllegalArgumentException("missing required 'password' option"); - var methodName = nonOptionArgs.get(0); + String methodName = nonOptionArgs.get(0); Method method; try { - method = getMethodFromCmd(methodName); + method = Method.valueOf(methodName.toLowerCase()); } catch (IllegalArgumentException ex) { throw new IllegalArgumentException(format("'%s' is not a supported method", methodName)); } @@ -191,50 +203,50 @@ public static void run(String[] args) { out.println(client.getMethodHelp(method)); return; } - var version = client.getVersion(); + String version = client.getVersion(); out.println(version); return; } case getbalance: { - var opts = new GetBalanceOptionParser(args).parse(); + GetBalanceOptionParser opts = new GetBalanceOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var currencyCode = opts.getCurrencyCode(); + String currencyCode = opts.getCurrencyCode(); var balances = client.getBalances(currencyCode); switch (currencyCode.toUpperCase()) { - case "BTC": - new TableBuilder(BTC_BALANCE_TBL, balances.getBtc()).build().print(out); + case "XMR": + new TableBuilder(XMR_BALANCE_TBL, balances.getXmr()).build().print(out); break; case "": default: { - out.println("BTC"); - new TableBuilder(BTC_BALANCE_TBL, balances.getBtc()).build().print(out); + out.println("XMR"); + new TableBuilder(XMR_BALANCE_TBL, balances.getXmr()).build().print(out); break; } } return; } case getaddressbalance: { - var opts = new GetAddressBalanceOptionParser(args).parse(); + GetAddressBalanceOptionParser opts = new GetAddressBalanceOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var address = opts.getAddress(); + String address = opts.getAddress(); var addressBalance = client.getAddressBalance(address); new TableBuilder(ADDRESS_BALANCE_TBL, addressBalance).build().print(out); return; } - case getbtcprice: { - var opts = new GetBTCMarketPriceOptionParser(args).parse(); + case getxmrprice: { + GetMarketPriceOptionParser opts = new GetMarketPriceOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var currencyCode = opts.getCurrencyCode(); - var price = client.getBtcPrice(currencyCode); + String currencyCode = opts.getCurrencyCode(); + double price = client.getXmrPrice(currencyCode); out.println(formatInternalFiatPrice(price)); return; } @@ -247,40 +259,93 @@ public static void run(String[] args) { new TableBuilder(ADDRESS_BALANCE_TBL, fundingAddresses).build().print(out); return; } - case sendbtc: { - var opts = new SendBtcOptionParser(args).parse(); + case getunusedxmraddress: { + if (new SimpleMethodOptionParser(args).parse().isForHelp()) { + out.println(client.getMethodHelp(method)); + return; + } + String address = client.getUnusedXmrAddress(); + out.println(address); + return; + } + case getxmrseed: { + if (new SimpleMethodOptionParser(args).parse().isForHelp()) { + out.println(client.getMethodHelp(method)); + return; + } + String seed = client.getXmrSeed(); + out.println(seed); + return; + } + case getxmrprimaryaddress: { + if (new SimpleMethodOptionParser(args).parse().isForHelp()) { + out.println(client.getMethodHelp(method)); + return; + } + String address = client.getXmrPrimaryAddress(); + out.println(address); + return; + } + case getxmrnewsubaddress: { + if (new SimpleMethodOptionParser(args).parse().isForHelp()) { + out.println(client.getMethodHelp(method)); + return; + } + String address = client.getXmrNewSubaddress(); + out.println(address); + return; + } + case getxmrtxs: { + if (new SimpleMethodOptionParser(args).parse().isForHelp()) { + out.println(client.getMethodHelp(method)); + return; + } + var txs = client.getXmrTxs(); + txs.forEach(tx -> out.println(tx)); + return; + } + case createxmrtx: { + CreateXmrTxOptionParser optionParser = new CreateXmrTxOptionParser(args); + OptionSet optionSet = optionParser.parse(args); + CreateXmrTxOptionParser.CreateXmrTxOptions opts = new CreateXmrTxOptionParser.CreateXmrTxOptions(optionSet); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var address = opts.getAddress(); - var amount = opts.getAmount(); - verifyStringIsValidDecimal(OPT_AMOUNT, amount); - - var txFeeRate = opts.getFeeRate(); - if (!txFeeRate.isEmpty()) - verifyStringIsValidLong(OPT_TX_FEE_RATE, txFeeRate); - - var memo = opts.getMemo(); - - throw new RuntimeException("Send BTC not implemented"); + List destinations = opts.getDestinations(); + var tx = client.createXmrTx(destinations); + out.println(tx); + return; + } + case relayxmrtxs: { + RelayXmrTxsOptionParser optionParser = new RelayXmrTxsOptionParser(args); + optionParser.parse(); + RelayXmrTxsOptionParser.RelayXmrTxsOptions opts = optionParser.getRelayXmrTxsOptions(); + if (opts.isForHelp()) { + out.println(client.getMethodHelp(method)); + return; + } + List metadatas = opts.getMetadatas(); + List hashes = client.relayXmrTxs(metadatas); + hashes.forEach(hash -> out.println(hash)); + return; } case createoffer: { - var opts = new CreateOfferOptionParser(args).parse(); + CreateOfferOptionParser opts = new CreateOfferOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var paymentAcctId = opts.getPaymentAccountId(); - var direction = opts.getDirection(); - var currencyCode = opts.getCurrencyCode(); - var amount = toSatoshis(opts.getAmount()); - var minAmount = toSatoshis(opts.getMinAmount()); - var useMarketBasedPrice = opts.isUsingMktPriceMargin(); - var fixedPrice = opts.getFixedPrice(); - var marketPriceMarginPct = opts.getMktPriceMarginPct(); - var securityDepositPct = opts.getSecurityDepositPct(); - var triggerPrice = "0"; // Cannot be defined until the new offer is added to book. + String paymentAcctId = opts.getPaymentAccountId(); + String direction = opts.getDirection(); + String currencyCode = opts.getCurrencyCode(); + long amount = toPiconeros(opts.getAmount()); + long minAmount = toPiconeros(opts.getMinAmount()); + boolean useMarketBasedPrice = opts.isUsingMktPriceMargin(); + String fixedPrice = opts.getFixedPrice(); + double marketPriceMarginPct = opts.getMktPriceMarginPct(); + double securityDepositPct = opts.getSecurityDepositPct(); + String triggerPrice = "0"; OfferInfo offer; offer = client.createOffer(direction, currencyCode, @@ -296,46 +361,46 @@ public static void run(String[] args) { return; } case canceloffer: { - var opts = new CancelOfferOptionParser(args).parse(); + CancelOfferOptionParser opts = new CancelOfferOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var offerId = opts.getOfferId(); + String offerId = opts.getOfferId(); client.cancelOffer(offerId); out.println("offer canceled and removed from offer book"); return; } case getoffer: { - var opts = new OfferIdOptionParser(args).parse(); + OfferIdOptionParser opts = new OfferIdOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var offerId = opts.getOfferId(); - var offer = client.getOffer(offerId); + String offerId = opts.getOfferId(); + OfferInfo offer = client.getOffer(offerId); new TableBuilder(OFFER_TBL, offer).build().print(out); return; } case getmyoffer: { - var opts = new OfferIdOptionParser(args).parse(); + OfferIdOptionParser opts = new OfferIdOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var offerId = opts.getOfferId(); - var offer = client.getMyOffer(offerId); + String offerId = opts.getOfferId(); + OfferInfo offer = client.getMyOffer(offerId); new TableBuilder(OFFER_TBL, offer).build().print(out); return; } case getoffers: { - var opts = new GetOffersOptionParser(args).parse(); + GetOffersOptionParser opts = new GetOffersOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var direction = opts.getDirection(); - var currencyCode = opts.getCurrencyCode(); + String direction = opts.getDirection(); + String currencyCode = opts.getCurrencyCode(); List offers = client.getOffers(direction, currencyCode); if (offers.isEmpty()) out.printf("no %s %s offers found%n", direction, currencyCode); @@ -345,13 +410,13 @@ public static void run(String[] args) { return; } case getmyoffers: { - var opts = new GetOffersOptionParser(args).parse(); + GetOffersOptionParser opts = new GetOffersOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var direction = opts.getDirection(); - var currencyCode = opts.getCurrencyCode(); + String direction = opts.getDirection(); + String currencyCode = opts.getCurrencyCode(); List offers = client.getMyOffers(direction, currencyCode); if (offers.isEmpty()) out.printf("no %s %s offers found%n", direction, currencyCode); @@ -362,26 +427,26 @@ public static void run(String[] args) { } case takeoffer: { - var opts = new TakeOfferOptionParser(args).parse(); + TakeOfferOptionParser opts = new TakeOfferOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var offerId = opts.getOfferId(); - var paymentAccountId = opts.getPaymentAccountId(); + String offerId = opts.getOfferId(); + String paymentAccountId = opts.getPaymentAccountId(); var trade = client.takeOffer(offerId, paymentAccountId); out.printf("trade %s successfully taken%n", trade.getTradeId()); return; } case gettrade: { // TODO make short-id a valid argument? - var opts = new GetTradeOptionParser(args).parse(); + GetTradeOptionParser opts = new GetTradeOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var tradeId = opts.getTradeId(); - var showContract = opts.getShowContract(); + String tradeId = opts.getTradeId(); + boolean showContract = opts.getShowContract(); var trade = client.getTrade(tradeId); if (showContract) out.println(trade.getContractAsJson()); @@ -391,7 +456,7 @@ public static void run(String[] args) { return; } case gettrades: { - var opts = new GetTradesOptionParser(args).parse(); + GetTradesOptionParser opts = new GetTradesOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; @@ -411,39 +476,39 @@ public static void run(String[] args) { return; } case confirmpaymentsent: { - var opts = new GetTradeOptionParser(args).parse(); + GetTradeOptionParser opts = new GetTradeOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var tradeId = opts.getTradeId(); + String tradeId = opts.getTradeId(); client.confirmPaymentSent(tradeId); out.printf("trade %s payment started message sent%n", tradeId); return; } case confirmpaymentreceived: { - var opts = new GetTradeOptionParser(args).parse(); + GetTradeOptionParser opts = new GetTradeOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var tradeId = opts.getTradeId(); + String tradeId = opts.getTradeId(); client.confirmPaymentReceived(tradeId); out.printf("trade %s payment received message sent%n", tradeId); return; } case withdrawfunds: { - var opts = new WithdrawFundsOptionParser(args).parse(); + WithdrawFundsOptionParser opts = new WithdrawFundsOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var tradeId = opts.getTradeId(); - var address = opts.getAddress(); + String tradeId = opts.getTradeId(); + String address = opts.getAddress(); // Multi-word memos must be double-quoted. - var memo = opts.getMemo(); + String memo = opts.getMemo(); client.withdrawFunds(tradeId, address, memo); - out.printf("trade %s funds sent to btc address %s%n", tradeId, address); + out.printf("trade %s funds sent to xmr address %s%n", tradeId, address); return; } case getpaymentmethods: { @@ -456,12 +521,12 @@ public static void run(String[] args) { return; } case getpaymentacctform: { - var opts = new GetPaymentAcctFormOptionParser(args).parse(); + GetPaymentAcctFormOptionParser opts = new GetPaymentAcctFormOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var paymentMethodId = opts.getPaymentMethodId(); + String paymentMethodId = opts.getPaymentMethodId(); String jsonString = client.getPaymentAcctFormAsJson(paymentMethodId); File jsonFile = saveFileToDisk(paymentMethodId.toLowerCase(), ".json", @@ -472,12 +537,12 @@ public static void run(String[] args) { return; } case createpaymentacct: { - var opts = new CreatePaymentAcctOptionParser(args).parse(); + CreatePaymentAcctOptionParser opts = new CreatePaymentAcctOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var paymentAccountForm = opts.getPaymentAcctForm(); + Path paymentAccountForm = opts.getPaymentAcctForm(); String jsonString; try { jsonString = new String(Files.readAllBytes(paymentAccountForm)); @@ -491,16 +556,16 @@ public static void run(String[] args) { return; } case createcryptopaymentacct: { - var opts = + CreateCryptoCurrencyPaymentAcctOptionParser opts = new CreateCryptoCurrencyPaymentAcctOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var accountName = opts.getAccountName(); - var currencyCode = opts.getCurrencyCode(); - var address = opts.getAddress(); - var isTradeInstant = opts.getIsTradeInstant(); + String accountName = opts.getAccountName(); + String currencyCode = opts.getCurrencyCode(); + String address = opts.getAddress(); + boolean isTradeInstant = opts.getIsTradeInstant(); var paymentAccount = client.createCryptoCurrencyPaymentAccount(accountName, currencyCode, address, @@ -532,48 +597,48 @@ public static void run(String[] args) { return; } case unlockwallet: { - var opts = new UnlockWalletOptionParser(args).parse(); + UnlockWalletOptionParser opts = new UnlockWalletOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var walletPassword = opts.getPassword(); - var timeout = opts.getUnlockTimeout(); + String walletPassword = opts.getPassword(); + long timeout = opts.getUnlockTimeout(); client.unlockWallet(walletPassword, timeout); out.println("wallet unlocked"); return; } case removewalletpassword: { - var opts = new RemoveWalletPasswordOptionParser(args).parse(); + RemoveWalletPasswordOptionParser opts = new RemoveWalletPasswordOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var walletPassword = opts.getPassword(); + String walletPassword = opts.getPassword(); client.removeWalletPassword(walletPassword); out.println("wallet decrypted"); return; } case setwalletpassword: { - var opts = new SetWalletPasswordOptionParser(args).parse(); + SetWalletPasswordOptionParser opts = new SetWalletPasswordOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var walletPassword = opts.getPassword(); - var newWalletPassword = opts.getNewPassword(); + String walletPassword = opts.getPassword(); + String newWalletPassword = opts.getNewPassword(); client.setWalletPassword(walletPassword, newWalletPassword); out.println("wallet encrypted" + (!newWalletPassword.isEmpty() ? " with new password" : "")); return; } case registerdisputeagent: { - var opts = new RegisterDisputeAgentOptionParser(args).parse(); + RegisterDisputeAgentOptionParser opts = new RegisterDisputeAgentOptionParser(args).parse(); if (opts.isForHelp()) { out.println(client.getMethodHelp(method)); return; } - var disputeAgentType = opts.getDisputeAgentType(); - var registrationKey = opts.getRegistrationKey(); + String disputeAgentType = opts.getDisputeAgentType(); + String registrationKey = opts.getRegistrationKey(); client.registerDisputeAgent(disputeAgentType, registrationKey); out.println(disputeAgentType + " registered"); return; @@ -661,7 +726,7 @@ private static File saveFileToDisk(String prefix, } } - private static void printHelp(OptionParser parser, @SuppressWarnings("SameParameterValue") PrintStream stream) { + private static void printHelp(OptionParser parser, PrintStream stream) { try { stream.println("Haveno RPC Client"); stream.println(); @@ -671,49 +736,38 @@ private static void printHelp(OptionParser parser, @SuppressWarnings("SameParame stream.println(); String rowFormat = "%-25s%-52s%s%n"; stream.format(rowFormat, "Method", "Params", "Description"); - stream.format(rowFormat, "------", "------", "------------"); + stream.format(rowFormat, "------", "------", "-----------"); stream.format(rowFormat, getversion.name(), "", "Get server version"); stream.println(); - stream.format(rowFormat, getbalance.name(), "[--currency-code=]", "Get server wallet balances"); + stream.format(rowFormat, getbalance.name(), "[--currency-code=]", "Get server wallet balances"); stream.println(); - stream.format(rowFormat, getaddressbalance.name(), "--address=", "Get server wallet address balance"); + stream.format(rowFormat, getaddressbalance.name(), "--address=", "Get server wallet address balance"); stream.println(); - stream.format(rowFormat, getbtcprice.name(), "--currency-code=", "Get current market btc price"); + stream.format(rowFormat, getxmrprice.name(), "--currency-code=", "Get current market xmr price"); stream.println(); - stream.format(rowFormat, getfundingaddresses.name(), "", "Get BTC funding addresses"); + stream.format(rowFormat, getfundingaddresses.name(), "", "Get XMR funding addresses"); stream.println(); - stream.format(rowFormat, getunusedbsqaddress.name(), "", "Get unused BSQ address"); + stream.format(rowFormat, getunusedxmraddress.name(), "", "Get unused XMR address"); stream.println(); - stream.format(rowFormat, "", "[--tx-fee-rate=]", ""); + stream.format(rowFormat, getxmrseed.name(), "", "Get XMR seed"); stream.println(); - stream.format(rowFormat, sendbtc.name(), "--address= --amount= \\", "Send BTC"); - stream.format(rowFormat, "", "[--tx-fee-rate=]", ""); - stream.format(rowFormat, "", "[--memo=<\"memo\">]", ""); + stream.format(rowFormat, getxmrprimaryaddress.name(), "", "Get XMR primary address"); stream.println(); - stream.format(rowFormat, gettxfeerate.name(), "", "Get current tx fee rate in sats/byte"); + stream.format(rowFormat, getxmrnewsubaddress.name(), "", "Get new XMR subaddress"); stream.println(); - stream.format(rowFormat, settxfeerate.name(), "--tx-fee-rate=", "Set custom tx fee rate in sats/byte"); + stream.format(rowFormat, getxmrtxs.name(), "", "Get XMR transactions"); stream.println(); - stream.format(rowFormat, unsettxfeerate.name(), "", "Unset custom tx fee rate"); + stream.format(rowFormat, createxmrtx.name(), "--destinations=", "Create XMR transaction"); stream.println(); - stream.format(rowFormat, gettransaction.name(), "--transaction-id=", "Get transaction with id"); + stream.format(rowFormat, relayxmrtxs.name(), "--metadatas=", "Relay XMR transactions"); stream.println(); stream.format(rowFormat, createoffer.name(), "--payment-account= \\", "Create and place an offer"); stream.format(rowFormat, "", "--direction= \\", ""); stream.format(rowFormat, "", "--currency-code= \\", ""); - stream.format(rowFormat, "", "--amount= \\", ""); - stream.format(rowFormat, "", "[--min-amount=] \\", ""); + stream.format(rowFormat, "", "--amount= \\", ""); + stream.format(rowFormat, "", "[--min-amount=] \\", ""); stream.format(rowFormat, "", "--fixed-price= | --market-price-margin= \\", ""); - stream.format(rowFormat, "", "--security-deposit= \\", ""); - stream.format(rowFormat, "", "[--fee-currency=]", ""); - stream.format(rowFormat, "", "[--trigger-price=]", ""); - stream.format(rowFormat, "", "[--swap=]", ""); - stream.println(); - stream.format(rowFormat, editoffer.name(), "--offer-id= \\", "Edit offer with id"); - stream.format(rowFormat, "", "[--fixed-price=] \\", ""); - stream.format(rowFormat, "", "[--market-price-margin=] \\", ""); - stream.format(rowFormat, "", "[--trigger-price=] \\", ""); - stream.format(rowFormat, "", "[--enabled=]", ""); + stream.format(rowFormat, "", "--security-deposit=", ""); stream.println(); stream.format(rowFormat, canceloffer.name(), "--offer-id=", "Cancel offer with id"); stream.println(); @@ -728,8 +782,7 @@ private static void printHelp(OptionParser parser, @SuppressWarnings("SameParame stream.format(rowFormat, "", "--currency-code=", ""); stream.println(); stream.format(rowFormat, takeoffer.name(), "--offer-id= \\", "Take offer with id"); - stream.format(rowFormat, "", "[--payment-account=]", ""); - stream.format(rowFormat, "", "[--fee-currency=]", ""); + stream.format(rowFormat, "", "--payment-account=", ""); stream.println(); stream.format(rowFormat, gettrade.name(), "--trade-id= \\", "Get trade summary or full contract"); stream.format(rowFormat, "", "[--show-contract=]", ""); @@ -740,16 +793,9 @@ private static void printHelp(OptionParser parser, @SuppressWarnings("SameParame stream.println(); stream.format(rowFormat, confirmpaymentreceived.name(), "--trade-id=", "Confirm payment received"); stream.println(); - stream.format(rowFormat, closetrade.name(), "--trade-id=", "Close completed trade"); - stream.println(); - stream.format(rowFormat, withdrawfunds.name(), "--trade-id= --address= \\", - "Withdraw received trade funds to external wallet address"); + stream.format(rowFormat, withdrawfunds.name(), "--trade-id= --address= \\", "Withdraw received trade funds to external wallet address"); stream.format(rowFormat, "", "[--memo=<\"memo\">]", ""); stream.println(); - stream.format(rowFormat, failtrade.name(), "--trade-id=", "Change open trade to failed trade"); - stream.println(); - stream.format(rowFormat, unfailtrade.name(), "--trade-id=", "Change failed trade to open trade"); - stream.println(); stream.format(rowFormat, getpaymentmethods.name(), "", "Get list of supported payment account method ids"); stream.println(); stream.format(rowFormat, getpaymentacctform.name(), "--payment-method-id=", "Get a new payment account form"); @@ -757,19 +803,17 @@ private static void printHelp(OptionParser parser, @SuppressWarnings("SameParame stream.format(rowFormat, createpaymentacct.name(), "--payment-account-form=", "Create a new payment account"); stream.println(); stream.format(rowFormat, createcryptopaymentacct.name(), "--account-name= \\", "Create a new cryptocurrency payment account"); - stream.format(rowFormat, "", "--currency-code= \\", ""); - stream.format(rowFormat, "", "--address=", ""); + stream.format(rowFormat, "", "--currency-code= \\", ""); + stream.format(rowFormat, "", "--address=", ""); stream.format(rowFormat, "", "--trade-instant=", ""); stream.println(); stream.format(rowFormat, getpaymentaccts.name(), "", "Get user payment accounts"); stream.println(); stream.format(rowFormat, lockwallet.name(), "", "Remove wallet password from memory, locking the wallet"); stream.println(); - stream.format(rowFormat, unlockwallet.name(), "--wallet-password= --timeout=", - "Store wallet password in memory for timeout seconds"); + stream.format(rowFormat, unlockwallet.name(), "--wallet-password= --timeout=", "Store wallet password in memory for timeout seconds"); stream.println(); - stream.format(rowFormat, setwalletpassword.name(), "--wallet-password= \\", - "Encrypt wallet with password, or set new password on encrypted wallet"); + stream.format(rowFormat, setwalletpassword.name(), "--wallet-password= \\", "Encrypt wallet with password, or set new password on encrypted wallet"); stream.format(rowFormat, "", "[--new-wallet-password=]", ""); stream.println(); stream.format(rowFormat, stop.name(), "", "Shut down the server"); diff --git a/cli/src/main/java/haveno/cli/ColumnHeaderConstants.java b/cli/src/main/java/haveno/cli/ColumnHeaderConstants.java index 5f1ef39e695..53c361068be 100644 --- a/cli/src/main/java/haveno/cli/ColumnHeaderConstants.java +++ b/cli/src/main/java/haveno/cli/ColumnHeaderConstants.java @@ -30,7 +30,7 @@ class ColumnHeaderConstants { // 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_AMOUNT = "XMR(min - max)"; static final String COL_HEADER_BALANCE = "Balance"; static final String COL_HEADER_AVAILABLE_BALANCE = "Available Balance"; static final String COL_HEADER_AVAILABLE_CONFIRMED_BALANCE = "Available Confirmed Balance"; @@ -51,8 +51,8 @@ class ColumnHeaderConstants { static final String COL_HEADER_DIRECTION = "Buy/Sell"; 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_CRYPTO = "Price in BTC for 1 %-3s"; + static final String COL_HEADER_PRICE = "Price in %-3s for 1 XMR"; + static final String COL_HEADER_PRICE_OF_CRYPTO = "Price in XMR for 1 %-3s"; static final String COL_HEADER_TRADE_AMOUNT = padStart("Amount(%-3s)", 12, ' '); static final String COL_HEADER_TRADE_BUYER_COST = padEnd("Buyer Cost(%-3s)", 15, ' '); static final String COL_HEADER_TRADE_DEPOSIT_CONFIRMED = "Deposit Confirmed"; @@ -63,14 +63,14 @@ class ColumnHeaderConstants { 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_TX_FEE = padEnd("Tx Fee(XMR)", 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_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_INPUT_SUM = "Tx Inputs (XMR)"; + static final String COL_HEADER_TX_OUTPUT_SUM = "Tx Outputs (XMR)"; + static final String COL_HEADER_TX_FEE = "Tx Fee (XMR)"; 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"; diff --git a/cli/src/main/java/haveno/cli/CurrencyFormat.java b/cli/src/main/java/haveno/cli/CurrencyFormat.java index c88b8c62e70..e30285a2fb9 100644 --- a/cli/src/main/java/haveno/cli/CurrencyFormat.java +++ b/cli/src/main/java/haveno/cli/CurrencyFormat.java @@ -44,32 +44,24 @@ public class CurrencyFormat { // Formats numbers for internal use, i.e., grpc request parameters. private static final DecimalFormat INTERNAL_FIAT_DECIMAL_FORMAT = new DecimalFormat("##############0.0000"); - static final BigDecimal SATOSHI_DIVISOR = new BigDecimal(100_000_000); - static final DecimalFormat SATOSHI_FORMAT = new DecimalFormat("###,##0.00000000", DECIMAL_FORMAT_SYMBOLS); - static final DecimalFormat BTC_FORMAT = new DecimalFormat("###,##0.########", DECIMAL_FORMAT_SYMBOLS); - static final DecimalFormat BTC_TX_FEE_FORMAT = new DecimalFormat("###,###,##0", DECIMAL_FORMAT_SYMBOLS); + static final BigDecimal PICONERO_DIVISOR = new BigDecimal(1_000_000_000_000L); + static final DecimalFormat PICONERO_FORMAT = new DecimalFormat("###,##0.000000000000", DECIMAL_FORMAT_SYMBOLS); + static final DecimalFormat XMR_FORMAT = new DecimalFormat("###,##0.############", DECIMAL_FORMAT_SYMBOLS); + static final DecimalFormat XMR_TX_FEE_FORMAT = new DecimalFormat("###,###,##0", DECIMAL_FORMAT_SYMBOLS); - static final BigDecimal BSQ_SATOSHI_DIVISOR = new BigDecimal(100); - static final DecimalFormat BSQ_FORMAT = new DecimalFormat("###,###,###,##0.00", DECIMAL_FORMAT_SYMBOLS); - - public static String formatSatoshis(String sats) { + public static String formatPiconeros(String piconeros) { //noinspection BigDecimalMethodWithoutRoundingCalled - return SATOSHI_FORMAT.format(new BigDecimal(sats).divide(SATOSHI_DIVISOR)); - } - - @SuppressWarnings("BigDecimalMethodWithoutRoundingCalled") - public static String formatSatoshis(long sats) { - return SATOSHI_FORMAT.format(new BigDecimal(sats).divide(SATOSHI_DIVISOR)); + return PICONERO_FORMAT.format(new BigDecimal(piconeros).divide(PICONERO_DIVISOR)); } @SuppressWarnings("BigDecimalMethodWithoutRoundingCalled") - public static String formatBtc(long sats) { - return BTC_FORMAT.format(new BigDecimal(sats).divide(SATOSHI_DIVISOR)); + public static String formatPiconeros(long piconeros) { + return PICONERO_FORMAT.format(new BigDecimal(piconeros).divide(PICONERO_DIVISOR)); } @SuppressWarnings("BigDecimalMethodWithoutRoundingCalled") - public static String formatBsq(long sats) { - return BSQ_FORMAT.format(new BigDecimal(sats).divide(BSQ_SATOSHI_DIVISOR)); + public static String formatXmr(long piconeros) { + return XMR_FORMAT.format(new BigDecimal(piconeros).divide(PICONERO_DIVISOR)); } public static String formatInternalFiatPrice(BigDecimal price) { @@ -98,18 +90,18 @@ public static String formatFiatVolume(long volume) { return US_LOCALE_NUMBER_FORMAT.format((double) volume / 10_000); } - public static long toSatoshis(String btc) { - if (btc.startsWith("-")) - throw new IllegalArgumentException(format("'%s' is not a positive number", btc)); + public static long toPiconeros(String xmr) { + if (xmr.startsWith("-")) + throw new IllegalArgumentException(format("'%s' is not a positive number", xmr)); try { - return new BigDecimal(btc).multiply(SATOSHI_DIVISOR).longValue(); + return new BigDecimal(xmr).multiply(PICONERO_DIVISOR).longValue(); } catch (NumberFormatException e) { - throw new IllegalArgumentException(format("'%s' is not a number", btc)); + throw new IllegalArgumentException(format("'%s' is not a number", xmr)); } } - public static String formatFeeSatoshis(long sats) { - return BTC_TX_FEE_FORMAT.format(BigDecimal.valueOf(sats)); + public static String formatFeePiconeros(long piconeros) { + return XMR_TX_FEE_FORMAT.format(BigDecimal.valueOf(piconeros)); } } diff --git a/cli/src/main/java/haveno/cli/GrpcClient.java b/cli/src/main/java/haveno/cli/GrpcClient.java index 229104ccde8..a29aa1ef6d3 100644 --- a/cli/src/main/java/haveno/cli/GrpcClient.java +++ b/cli/src/main/java/haveno/cli/GrpcClient.java @@ -23,7 +23,6 @@ import haveno.cli.request.WalletsServiceRequest; import haveno.proto.grpc.AddressBalanceInfo; import haveno.proto.grpc.BalancesInfo; -import haveno.proto.grpc.BtcBalanceInfo; import haveno.proto.grpc.GetMethodHelpRequest; import haveno.proto.grpc.GetTradesRequest; import haveno.proto.grpc.GetVersionRequest; @@ -31,6 +30,9 @@ import haveno.proto.grpc.RegisterDisputeAgentRequest; import haveno.proto.grpc.StopRequest; import haveno.proto.grpc.TradeInfo; +import haveno.proto.grpc.XmrBalanceInfo; +import haveno.proto.grpc.XmrTx; +import haveno.proto.grpc.XmrDestination; import lombok.extern.slf4j.Slf4j; import protobuf.PaymentAccount; import protobuf.PaymentMethod; @@ -67,8 +69,8 @@ public BalancesInfo getBalances() { return walletsServiceRequest.getBalances(); } - public BtcBalanceInfo getBtcBalances() { - return walletsServiceRequest.getBtcBalances(); + public XmrBalanceInfo getXmrBalances() { + return walletsServiceRequest.getXmrBalances(); } public BalancesInfo getBalances(String currencyCode) { @@ -79,16 +81,44 @@ public AddressBalanceInfo getAddressBalance(String address) { return walletsServiceRequest.getAddressBalance(address); } - public double getBtcPrice(String currencyCode) { - return walletsServiceRequest.getBtcPrice(currencyCode); + public double getXmrPrice(String currencyCode) { + return walletsServiceRequest.getXmrPrice(currencyCode); } public List getFundingAddresses() { return walletsServiceRequest.getFundingAddresses(); } - public String getUnusedBtcAddress() { - return walletsServiceRequest.getUnusedBtcAddress(); + public String getUnusedXmrAddress() { + return walletsServiceRequest.getUnusedXmrAddress(); + } + + public String getXmrSeed() { + return walletsServiceRequest.getXmrSeed(); + } + + public String getXmrPrimaryAddress() { + return walletsServiceRequest.getXmrPrimaryAddress(); + } + + public String getXmrNewSubaddress() { + return walletsServiceRequest.getXmrNewSubaddress(); + } + + public List getXmrTxs() { + return walletsServiceRequest.getXmrTxs(); + } + + public XmrTx createXmrTx(List destinations) { + return walletsServiceRequest.createXmrTx(destinations); + } + + public List relayXmrTxs(List metadatas) { + return walletsServiceRequest.relayXmrTxs(metadatas); + } + + public List createXmrSweepTxs(String address) { + return walletsServiceRequest.createXmrSweepTxs(address); } public OfferInfo createFixedPricedOffer(String direction, diff --git a/cli/src/main/java/haveno/cli/Method.java b/cli/src/main/java/haveno/cli/Method.java index f83416c3b18..2162407d27c 100644 --- a/cli/src/main/java/haveno/cli/Method.java +++ b/cli/src/main/java/haveno/cli/Method.java @@ -31,7 +31,7 @@ public enum Method { createcryptopaymentacct, getaddressbalance, getbalance, - getbtcprice, + getxmrprice, getfundingaddresses, @Deprecated // Since 27-Dec-2021. getmyoffer, // Endpoint to be removed from future version. Use getoffer instead. @@ -52,12 +52,18 @@ public enum Method { lockwallet, registerdisputeagent, removewalletpassword, - sendbtc, settxfeerate, setwalletpassword, takeoffer, unlockwallet, unsettxfeerate, withdrawfunds, - stop + stop, + getunusedxmraddress, + getxmrseed, + getxmrprimaryaddress, + getxmrnewsubaddress, + getxmrtxs, + createxmrtx, + relayxmrtxs } diff --git a/cli/src/main/java/haveno/cli/opts/CreateXmrTxOptionParser.java b/cli/src/main/java/haveno/cli/opts/CreateXmrTxOptionParser.java new file mode 100644 index 00000000000..c3758ba5408 --- /dev/null +++ b/cli/src/main/java/haveno/cli/opts/CreateXmrTxOptionParser.java @@ -0,0 +1,39 @@ +package haveno.cli.opts; + +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import java.util.ArrayList; +import java.util.List; +import haveno.proto.grpc.XmrDestination; + +public class CreateXmrTxOptionParser extends OptionParser { + + public CreateXmrTxOptionParser(String[] args) { + accepts("destinations", "List of destinations for the XMR transaction") + .withRequiredArg() + .ofType(String.class); + } + + public OptionSet parse(String[] args) { + return super.parse(args); + } + + public static class CreateXmrTxOptions { + private final OptionSet options; + + public CreateXmrTxOptions(OptionSet options) { + this.options = options; + } + + public boolean isForHelp() { + return options.has("help"); + } + + public List getDestinations() { + List destinations = new ArrayList<>(); + // Parse the destinations from the options and populate the list + // This is a placeholder; you need to implement the actual parsing logic + return destinations; + } + } +} diff --git a/cli/src/main/java/haveno/cli/opts/GetMarketPriceOptionParser.java b/cli/src/main/java/haveno/cli/opts/GetMarketPriceOptionParser.java new file mode 100644 index 00000000000..2eb30af703e --- /dev/null +++ b/cli/src/main/java/haveno/cli/opts/GetMarketPriceOptionParser.java @@ -0,0 +1,50 @@ +/* + * 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 haveno.cli.opts; + + +import joptsimple.OptionSpec; + +import static haveno.cli.opts.OptLabel.OPT_CURRENCY_CODE; + +public class GetMarketPriceOptionParser extends AbstractMethodOptionParser implements MethodOpts { + + final OptionSpec currencyCodeOpt = parser.accepts(OPT_CURRENCY_CODE, "currency-code") + .withRequiredArg(); + + public GetMarketPriceOptionParser(String[] args) { + super(args); + } + + public GetMarketPriceOptionParser parse() { + super.parse(); + + // Short circuit opt validation if user just wants help. + if (options.has(helpOpt)) + return this; + + if (!options.has(currencyCodeOpt) || options.valueOf(currencyCodeOpt).isEmpty()) + throw new IllegalArgumentException("no currency code specified"); + + return this; + } + + public String getCurrencyCode() { + return options.valueOf(currencyCodeOpt); + } +} diff --git a/cli/src/main/java/haveno/cli/opts/RelayXmrTxsOptionParser.java b/cli/src/main/java/haveno/cli/opts/RelayXmrTxsOptionParser.java new file mode 100644 index 00000000000..0cf1e3e7d3d --- /dev/null +++ b/cli/src/main/java/haveno/cli/opts/RelayXmrTxsOptionParser.java @@ -0,0 +1,42 @@ +package haveno.cli.opts; + +import joptsimple.OptionSet; + +import java.util.List; + +public class RelayXmrTxsOptionParser extends AbstractMethodOptionParser { + + public RelayXmrTxsOptionParser(String[] args) { + super(args); + parser.accepts("metadatas", "Metadata for the XMR transactions") + .withRequiredArg() + .ofType(String.class) + .withValuesSeparatedBy(','); + } + + @Override + public RelayXmrTxsOptionParser parse() { + super.parse(); + return this; + } + + public RelayXmrTxsOptions getRelayXmrTxsOptions() { + return new RelayXmrTxsOptions(options); + } + + public static class RelayXmrTxsOptions { + private final OptionSet options; + + public RelayXmrTxsOptions(OptionSet options) { + this.options = options; + } + + public boolean isForHelp() { + return options.has("help"); + } + + public List getMetadatas() { + return (List) options.valuesOf("metadatas"); + } + } +} diff --git a/cli/src/main/java/haveno/cli/opts/SendBtcOptionParser.java b/cli/src/main/java/haveno/cli/opts/SendXmrOptionParser.java similarity index 90% rename from cli/src/main/java/haveno/cli/opts/SendBtcOptionParser.java rename to cli/src/main/java/haveno/cli/opts/SendXmrOptionParser.java index 12eec3bc5a8..4637ac1ea1f 100644 --- a/cli/src/main/java/haveno/cli/opts/SendBtcOptionParser.java +++ b/cli/src/main/java/haveno/cli/opts/SendXmrOptionParser.java @@ -26,15 +26,15 @@ import static haveno.cli.opts.OptLabel.OPT_TX_FEE_RATE; import static joptsimple.internal.Strings.EMPTY; -public class SendBtcOptionParser extends AbstractMethodOptionParser implements MethodOpts { +public class SendXmrOptionParser extends AbstractMethodOptionParser implements MethodOpts { - final OptionSpec addressOpt = parser.accepts(OPT_ADDRESS, "destination btc address") + final OptionSpec addressOpt = parser.accepts(OPT_ADDRESS, "destination xmr address") .withRequiredArg(); - final OptionSpec amountOpt = parser.accepts(OPT_AMOUNT, "amount of btc to send") + final OptionSpec amountOpt = parser.accepts(OPT_AMOUNT, "amount of xmr to send") .withRequiredArg(); - final OptionSpec feeRateOpt = parser.accepts(OPT_TX_FEE_RATE, "optional tx fee rate (sats/byte)") + final OptionSpec feeRateOpt = parser.accepts(OPT_TX_FEE_RATE, "optional tx fee rate (piconero/byte)") .withOptionalArg() .defaultsTo(EMPTY); @@ -42,11 +42,11 @@ public class SendBtcOptionParser extends AbstractMethodOptionParser implements M .withOptionalArg() .defaultsTo(EMPTY); - public SendBtcOptionParser(String[] args) { + public SendXmrOptionParser(String[] args) { super(args); } - public SendBtcOptionParser parse() { + public SendXmrOptionParser parse() { super.parse(); // Short circuit opt validation if user just wants help. diff --git a/cli/src/main/java/haveno/cli/request/WalletsServiceRequest.java b/cli/src/main/java/haveno/cli/request/WalletsServiceRequest.java index dde9ce2529a..9f404c74fe4 100644 --- a/cli/src/main/java/haveno/cli/request/WalletsServiceRequest.java +++ b/cli/src/main/java/haveno/cli/request/WalletsServiceRequest.java @@ -20,15 +20,24 @@ import haveno.cli.GrpcStubs; import haveno.proto.grpc.AddressBalanceInfo; import haveno.proto.grpc.BalancesInfo; -import haveno.proto.grpc.BtcBalanceInfo; +import haveno.proto.grpc.XmrBalanceInfo; import haveno.proto.grpc.GetAddressBalanceRequest; import haveno.proto.grpc.GetBalancesRequest; import haveno.proto.grpc.GetFundingAddressesRequest; +import haveno.proto.grpc.GetXmrSeedRequest; +import haveno.proto.grpc.GetXmrPrimaryAddressRequest; +import haveno.proto.grpc.GetXmrNewSubaddressRequest; +import haveno.proto.grpc.GetXmrTxsRequest; import haveno.proto.grpc.LockWalletRequest; import haveno.proto.grpc.MarketPriceRequest; import haveno.proto.grpc.RemoveWalletPasswordRequest; import haveno.proto.grpc.SetWalletPasswordRequest; import haveno.proto.grpc.UnlockWalletRequest; +import haveno.proto.grpc.XmrTx; +import haveno.proto.grpc.CreateXmrTxRequest; +import haveno.proto.grpc.RelayXmrTxsRequest; +import haveno.proto.grpc.CreateXmrSweepTxsRequest; +import haveno.proto.grpc.XmrDestination; import java.util.List; @@ -44,8 +53,8 @@ public BalancesInfo getBalances() { return getBalances(""); } - public BtcBalanceInfo getBtcBalances() { - return getBalances("BTC").getBtc(); + public XmrBalanceInfo getXmrBalances() { + return getBalances("XMR").getXmr(); } public BalancesInfo getBalances(String currencyCode) { @@ -61,7 +70,7 @@ public AddressBalanceInfo getAddressBalance(String address) { return grpcStubs.walletsService.getAddressBalance(request).getAddressBalanceInfo(); } - public double getBtcPrice(String currencyCode) { + public double getXmrPrice(String currencyCode) { var request = MarketPriceRequest.newBuilder() .setCurrencyCode(currencyCode) .build(); @@ -73,7 +82,7 @@ public List getFundingAddresses() { return grpcStubs.walletsService.getFundingAddresses(request).getAddressBalanceInfoList(); } - public String getUnusedBtcAddress() { + public String getUnusedXmrAddress() { var request = GetFundingAddressesRequest.newBuilder().build(); var addressBalances = grpcStubs.walletsService.getFundingAddresses(request) .getAddressBalanceInfoList(); @@ -85,6 +94,47 @@ public String getUnusedBtcAddress() { .getAddress(); } + public String getXmrSeed() { + var request = GetXmrSeedRequest.newBuilder().build(); + return grpcStubs.walletsService.getXmrSeed(request).getSeed(); + } + + public String getXmrPrimaryAddress() { + var request = GetXmrPrimaryAddressRequest.newBuilder().build(); + return grpcStubs.walletsService.getXmrPrimaryAddress(request).getPrimaryAddress(); + } + + public String getXmrNewSubaddress() { + var request = GetXmrNewSubaddressRequest.newBuilder().build(); + return grpcStubs.walletsService.getXmrNewSubaddress(request).getSubaddress(); + } + + public List getXmrTxs() { + var request = GetXmrTxsRequest.newBuilder().build(); + return grpcStubs.walletsService.getXmrTxs(request).getTxsList(); + } + + public XmrTx createXmrTx(List destinations) { + var request = CreateXmrTxRequest.newBuilder() + .addAllDestinations(destinations) + .build(); + return grpcStubs.walletsService.createXmrTx(request).getTx(); + } + + public List relayXmrTxs(List metadatas) { + var request = RelayXmrTxsRequest.newBuilder() + .addAllMetadatas(metadatas) + .build(); + return grpcStubs.walletsService.relayXmrTxs(request).getHashesList(); + } + + public List createXmrSweepTxs(String address) { + var request = CreateXmrSweepTxsRequest.newBuilder() + .setAddress(address) + .build(); + return grpcStubs.walletsService.createXmrSweepTxs(request).getTxsList(); + } + public void lockWallet() { var request = LockWalletRequest.newBuilder().build(); //noinspection ResultOfMethodCallIgnored diff --git a/cli/src/main/java/haveno/cli/table/builder/AbstractTradeListBuilder.java b/cli/src/main/java/haveno/cli/table/builder/AbstractTradeListBuilder.java index b279f68b8e1..a8143681d9a 100644 --- a/cli/src/main/java/haveno/cli/table/builder/AbstractTradeListBuilder.java +++ b/cli/src/main/java/haveno/cli/table/builder/AbstractTradeListBuilder.java @@ -30,7 +30,7 @@ import java.util.function.Supplier; import java.util.stream.Collectors; -import static haveno.cli.CurrencyFormat.formatSatoshis; +import static haveno.cli.CurrencyFormat.formatPiconeros; import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_BUYER_DEPOSIT; import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_SELLER_DEPOSIT; import static haveno.cli.table.builder.TableType.TRADE_DETAIL_TBL; @@ -146,7 +146,7 @@ protected void validate() { protected final Predicate isMyOffer = (t) -> t.getOffer().getIsMyOffer(); protected final Predicate isTaker = (t) -> t.getRole().toLowerCase().contains("taker"); protected final Predicate isSellOffer = (t) -> t.getOffer().getDirection().equals(SELL.name()); - protected final Predicate isBtcSeller = (t) -> (isMyOffer.test(t) && isSellOffer.test(t)) + protected final Predicate isXmrSeller = (t) -> (isMyOffer.test(t) && isSellOffer.test(t)) || (!isMyOffer.test(t) && !isSellOffer.test(t)); @@ -160,7 +160,7 @@ protected void validate() { protected final Function toTradeVolumeAsString = (t) -> isTraditionalTrade.test(t) ? t.getTradeVolume() - : formatSatoshis(t.getAmount()); + : formatPiconeros(t.getAmount()); protected final Function toTradeVolumeAsLong = (t) -> isTraditionalTrade.test(t) @@ -186,7 +186,7 @@ protected void validate() { ? format("%.2f%s", t.getOffer().getMarketPriceMarginPct(), "%") : "N/A"; - protected final Function toTradeFeeBtc = (t) -> { + protected final Function toTradeFeeXmr = (t) -> { var isMyOffer = t.getOffer().getIsMyOffer(); if (isMyOffer) { return t.getMakerFee(); diff --git a/cli/src/main/java/haveno/cli/table/builder/AddressBalanceTableBuilder.java b/cli/src/main/java/haveno/cli/table/builder/AddressBalanceTableBuilder.java index 4c26d30c055..20c3a467c93 100644 --- a/cli/src/main/java/haveno/cli/table/builder/AddressBalanceTableBuilder.java +++ b/cli/src/main/java/haveno/cli/table/builder/AddressBalanceTableBuilder.java @@ -21,7 +21,7 @@ import haveno.cli.table.column.BooleanColumn; import haveno.cli.table.column.Column; import haveno.cli.table.column.LongColumn; -import haveno.cli.table.column.SatoshiColumn; +import haveno.cli.table.column.PiconeroColumn; import haveno.cli.table.column.StringColumn; import haveno.proto.grpc.AddressBalanceInfo; @@ -49,8 +49,8 @@ class AddressBalanceTableBuilder extends AbstractTableBuilder { AddressBalanceTableBuilder(List protos) { super(ADDRESS_BALANCE_TBL, protos); - colAddress = new StringColumn(format(COL_HEADER_ADDRESS, "BTC")); - this.colAvailableBalance = new SatoshiColumn(COL_HEADER_AVAILABLE_BALANCE); + colAddress = new StringColumn(format(COL_HEADER_ADDRESS, "XMR")); + this.colAvailableBalance = new PiconeroColumn(COL_HEADER_AVAILABLE_BALANCE); this.colConfirmations = new LongColumn(COL_HEADER_CONFIRMATIONS); this.colIsUsed = new BooleanColumn(COL_HEADER_IS_USED_ADDRESS); } diff --git a/cli/src/main/java/haveno/cli/table/builder/BtcBalanceTableBuilder.java b/cli/src/main/java/haveno/cli/table/builder/BtcBalanceTableBuilder.java deleted file mode 100644 index 41f3a18f38b..00000000000 --- a/cli/src/main/java/haveno/cli/table/builder/BtcBalanceTableBuilder.java +++ /dev/null @@ -1,71 +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 haveno.cli.table.builder; - -import haveno.cli.table.Table; -import haveno.cli.table.column.Column; -import haveno.cli.table.column.SatoshiColumn; -import haveno.proto.grpc.BtcBalanceInfo; - -import java.util.List; - -import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_AVAILABLE_BALANCE; -import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_LOCKED_BALANCE; -import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_RESERVED_BALANCE; -import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_TOTAL_AVAILABLE_BALANCE; -import static haveno.cli.table.builder.TableType.BTC_BALANCE_TBL; - -/** - * Builds a {@code haveno.cli.table.Table} from a - * {@code haveno.proto.grpc.BtcBalanceInfo} object. - */ -class BtcBalanceTableBuilder extends AbstractTableBuilder { - - // Default columns not dynamically generated with btc balance info. - private final Column colAvailableBalance; - private final Column colReservedBalance; - private final Column colTotalAvailableBalance; - private final Column colLockedBalance; - - BtcBalanceTableBuilder(List protos) { - super(BTC_BALANCE_TBL, protos); - this.colAvailableBalance = new SatoshiColumn(COL_HEADER_AVAILABLE_BALANCE); - this.colReservedBalance = new SatoshiColumn(COL_HEADER_RESERVED_BALANCE); - this.colTotalAvailableBalance = new SatoshiColumn(COL_HEADER_TOTAL_AVAILABLE_BALANCE); - this.colLockedBalance = new SatoshiColumn(COL_HEADER_LOCKED_BALANCE); - } - - @Override - public Table build() { - BtcBalanceInfo balance = (BtcBalanceInfo) protos.get(0); - - // Populate columns with btc balance info. - - colAvailableBalance.addRow(balance.getAvailableBalance()); - colReservedBalance.addRow(balance.getReservedBalance()); - colTotalAvailableBalance.addRow(balance.getTotalAvailableBalance()); - colLockedBalance.addRow(balance.getLockedBalance()); - - // Define and return the table instance with populated columns. - - return new Table(colAvailableBalance.asStringColumn(), - colReservedBalance.asStringColumn(), - colTotalAvailableBalance.asStringColumn(), - colLockedBalance.asStringColumn()); - } -} diff --git a/cli/src/main/java/haveno/cli/table/builder/ClosedTradeTableBuilder.java b/cli/src/main/java/haveno/cli/table/builder/ClosedTradeTableBuilder.java index c57baf63d8d..122c4b296c1 100644 --- a/cli/src/main/java/haveno/cli/table/builder/ClosedTradeTableBuilder.java +++ b/cli/src/main/java/haveno/cli/table/builder/ClosedTradeTableBuilder.java @@ -59,7 +59,7 @@ private void populateColumns() { colMixedAmount.addRow(t.getTradeVolume()); colCurrency.addRow(toPaymentCurrencyCode.apply(t)); - colMixedTradeFee.addRow(toTradeFeeBtc.apply(t), false); + colMixedTradeFee.addRow(toTradeFeeXmr.apply(t)); colBuyerDeposit.addRow(t.getOffer().getBuyerSecurityDepositPct()); colSellerDeposit.addRow(t.getOffer().getSellerSecurityDepositPct()); diff --git a/cli/src/main/java/haveno/cli/table/builder/OfferTableBuilder.java b/cli/src/main/java/haveno/cli/table/builder/OfferTableBuilder.java index 23b93ca6ae0..19ea1ec757f 100644 --- a/cli/src/main/java/haveno/cli/table/builder/OfferTableBuilder.java +++ b/cli/src/main/java/haveno/cli/table/builder/OfferTableBuilder.java @@ -20,7 +20,7 @@ import haveno.cli.table.Table; import haveno.cli.table.column.Column; import haveno.cli.table.column.Iso8601DateTimeColumn; -import haveno.cli.table.column.SatoshiColumn; +import haveno.cli.table.column.PiconeroColumn; import haveno.cli.table.column.StringColumn; import haveno.cli.table.column.ZippedStringColumns; import haveno.proto.grpc.OfferInfo; @@ -59,8 +59,8 @@ class OfferTableBuilder extends AbstractTableBuilder { // Columns common to both traditional and cryptocurrency offers. private final Column colOfferId = new StringColumn(COL_HEADER_UUID, LEFT); private final Column colDirection = new StringColumn(COL_HEADER_DIRECTION, LEFT); - private final Column colAmount = new SatoshiColumn("Temp Amount", NONE); - private final Column colMinAmount = new SatoshiColumn("Temp Min Amount", NONE); + private final Column colAmount = new PiconeroColumn("Temp Amount", NONE); + private final Column colMinAmount = new PiconeroColumn("Temp Min Amount", NONE); private final Column colPaymentMethod = new StringColumn(COL_HEADER_PAYMENT_METHOD, LEFT); private final Column colCreateDate = new Iso8601DateTimeColumn(COL_HEADER_CREATION_DATE); @@ -142,7 +142,7 @@ public Table buildTraditionalOfferTable(List offers) { 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_CRYPTO, cryptoTradeCurrency.get()), RIGHT); + Column colXmrPrice = new StringColumn(format(COL_HEADER_DETAILED_PRICE_OF_CRYPTO, cryptoTradeCurrency.get()), RIGHT); Column colVolume = new StringColumn(format("Temp Volume (%s)", cryptoTradeCurrency.get()), NONE); Column colMinVolume = new StringColumn(format("Temp Min Volume (%s)", cryptoTradeCurrency.get()), NONE); @Nullable @@ -155,7 +155,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { colEnabled.addRow(toEnabled.apply(o)); colDirection.addRow(directionFormat.apply(o)); - colBtcPrice.addRow(o.getPrice()); + colXmrPrice.addRow(o.getPrice()); colAmount.addRow(o.getAmount()); colMinAmount.addRow(o.getMinAmount()); colVolume.addRow(o.getVolume()); @@ -183,7 +183,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { if (isShowingBsqOffers.get()) { return new Table(colEnabled.asStringColumn(), colDirection, - colBtcPrice.justify(), + colXmrPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colPaymentMethod, @@ -192,7 +192,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { } else { return new Table(colEnabled.asStringColumn(), colDirection, - colBtcPrice.justify(), + colXmrPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colTriggerPrice.justify(), @@ -202,7 +202,7 @@ public Table buildCryptoCurrencyOfferTable(List offers) { } } else { return new Table(colDirection, - colBtcPrice.justify(), + colXmrPrice.justify(), amountRange.asStringColumn(EXCLUDE_DUPLICATES), volumeRange.asStringColumn(EXCLUDE_DUPLICATES), colPaymentMethod, diff --git a/cli/src/main/java/haveno/cli/table/builder/TableBuilder.java b/cli/src/main/java/haveno/cli/table/builder/TableBuilder.java index cff4dde629c..626653c1548 100644 --- a/cli/src/main/java/haveno/cli/table/builder/TableBuilder.java +++ b/cli/src/main/java/haveno/cli/table/builder/TableBuilder.java @@ -44,8 +44,8 @@ public Table build() { switch (tableType) { case ADDRESS_BALANCE_TBL: return new AddressBalanceTableBuilder(protos).build(); - case BTC_BALANCE_TBL: - return new BtcBalanceTableBuilder(protos).build(); + case XMR_BALANCE_TBL: + return new XmrBalanceTableBuilder(protos).build(); case CLOSED_TRADES_TBL: return new ClosedTradeTableBuilder(protos).build(); case FAILED_TRADES_TBL: diff --git a/cli/src/main/java/haveno/cli/table/builder/TableBuilderConstants.java b/cli/src/main/java/haveno/cli/table/builder/TableBuilderConstants.java index 893f9f8bf24..fbe2de91a1c 100644 --- a/cli/src/main/java/haveno/cli/table/builder/TableBuilderConstants.java +++ b/cli/src/main/java/haveno/cli/table/builder/TableBuilderConstants.java @@ -23,8 +23,8 @@ class TableBuilderConstants { static final String COL_HEADER_ADDRESS = "%-3s Address"; static final String COL_HEADER_AMOUNT = "Amount"; - static final String COL_HEADER_AMOUNT_IN_BTC = "Amount in BTC"; - static final String COL_HEADER_AMOUNT_RANGE = "BTC(min - max)"; + static final String COL_HEADER_AMOUNT_IN_XMR = "Amount in XMR"; + static final String COL_HEADER_AMOUNT_RANGE = "XMR(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"; @@ -36,8 +36,8 @@ class TableBuilderConstants { 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_BSQ_SWAP_TRADE_ROLE = "My BSQ Swap Role"; - static final String COL_HEADER_BUYER_DEPOSIT = "Buyer Deposit (BTC)"; - static final String COL_HEADER_SELLER_DEPOSIT = "Seller Deposit (BTC)"; + static final String COL_HEADER_BUYER_DEPOSIT = "Buyer Deposit (XMR)"; + static final String COL_HEADER_SELLER_DEPOSIT = "Seller Deposit (XMR)"; static final String COL_HEADER_CONFIRMATIONS = "Confirmations"; static final String COL_HEADER_DEVIATION = "Deviation"; static final String COL_HEADER_IS_USED_ADDRESS = "Is Used"; @@ -45,8 +45,8 @@ class TableBuilderConstants { static final String COL_HEADER_CURRENCY = "Currency"; static final String COL_HEADER_DATE_TIME = "Date/Time (UTC)"; static final String COL_HEADER_DETAILED_AMOUNT = "Amount(%-3s)"; - static final String COL_HEADER_DETAILED_PRICE = "Price in %-3s for 1 BTC"; - static final String COL_HEADER_DETAILED_PRICE_OF_CRYPTO = "Price in BTC for 1 %-3s"; + static final String COL_HEADER_DETAILED_PRICE = "Price in %-3s for 1 XMR"; + static final String COL_HEADER_DETAILED_PRICE_OF_CRYPTO = "Price in XMR for 1 %-3s"; static final String COL_HEADER_DIRECTION = "Buy/Sell"; static final String COL_HEADER_ENABLED = "Enabled"; static final String COL_HEADER_MARKET = "Market"; @@ -71,9 +71,9 @@ class TableBuilderConstants { static final String COL_HEADER_TRADE_FEE = "Trade Fee"; 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_INPUT_SUM = "Tx Inputs (XMR)"; + static final String COL_HEADER_TX_OUTPUT_SUM = "Tx Outputs (XMR)"; + static final String COL_HEADER_TX_FEE = "Tx Fee (XMR)"; 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"; diff --git a/cli/src/main/java/haveno/cli/table/builder/TableType.java b/cli/src/main/java/haveno/cli/table/builder/TableType.java index 871240abb3d..4589429fa56 100644 --- a/cli/src/main/java/haveno/cli/table/builder/TableType.java +++ b/cli/src/main/java/haveno/cli/table/builder/TableType.java @@ -23,7 +23,7 @@ */ public enum TableType { ADDRESS_BALANCE_TBL, - BTC_BALANCE_TBL, + XMR_BALANCE_TBL, CLOSED_TRADES_TBL, FAILED_TRADES_TBL, OFFER_TBL, diff --git a/cli/src/main/java/haveno/cli/table/builder/TradeTableColumnSupplier.java b/cli/src/main/java/haveno/cli/table/builder/TradeTableColumnSupplier.java index d1974344dff..78a2aaa01a5 100644 --- a/cli/src/main/java/haveno/cli/table/builder/TradeTableColumnSupplier.java +++ b/cli/src/main/java/haveno/cli/table/builder/TradeTableColumnSupplier.java @@ -20,11 +20,11 @@ import haveno.cli.table.column.CryptoVolumeColumn; import haveno.cli.table.column.DoubleColumn; import haveno.cli.table.column.BooleanColumn; -import haveno.cli.table.column.BtcColumn; +import haveno.cli.table.column.XmrColumn; import haveno.cli.table.column.Column; import haveno.cli.table.column.Iso8601DateTimeColumn; import haveno.cli.table.column.MixedTradeFeeColumn; -import haveno.cli.table.column.SatoshiColumn; +import haveno.cli.table.column.PiconeroColumn; import haveno.cli.table.column.StringColumn; import haveno.proto.grpc.ContractInfo; import haveno.proto.grpc.OfferInfo; @@ -39,7 +39,7 @@ import java.util.function.Supplier; import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_AMOUNT; -import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_AMOUNT_IN_BTC; +import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_AMOUNT_IN_XMR; import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_CURRENCY; import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_DATE_TIME; import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_DETAILED_AMOUNT; @@ -138,7 +138,7 @@ public TradeTableColumnSupplier(TableType tableType, List trades) { String colHeader = format(COL_HEADER_DETAILED_AMOUNT, headerCurrencyCode); CryptoVolumeColumn.DISPLAY_MODE displayMode = headerCurrencyCode.equals("BSQ") ? BSQ_VOLUME : CRYPTO_VOLUME; return isTraditionalTrade.test(t) - ? new SatoshiColumn(colHeader) + ? new PiconeroColumn(colHeader) : new CryptoVolumeColumn(colHeader, displayMode); }; @@ -146,14 +146,14 @@ public TradeTableColumnSupplier(TableType tableType, List trades) { // in the displayed string representation is done in the Column implementation. final Supplier> amountColumn = () -> isTradeDetailTblBuilder.get() ? toDetailedAmountColumn.apply(firstRow.get()) - : new BtcColumn(COL_HEADER_AMOUNT_IN_BTC); + : new XmrColumn(COL_HEADER_AMOUNT_IN_XMR); final Supplier mixedAmountColumn = () -> isTradeDetailTblBuilder.get() ? null : new StringColumn(COL_HEADER_AMOUNT, RIGHT); final Supplier> minerTxFeeColumn = () -> isTradeDetailTblBuilder.get() || isClosedTradeTblBuilder.get() - ? new SatoshiColumn(COL_HEADER_TX_FEE) + ? new PiconeroColumn(COL_HEADER_TX_FEE) : null; final Supplier mixedTradeFeeColumn = () -> isTradeDetailTblBuilder.get() @@ -216,7 +216,7 @@ public TradeTableColumnSupplier(TableType tableType, List trades) { String colHeader = isTaker.test(t) ? format(COL_HEADER_TRADE_TAKER_FEE, headerCurrencyCode) : format(COL_HEADER_TRADE_MAKER_FEE, headerCurrencyCode); - return new SatoshiColumn(colHeader, false); + return new PiconeroColumn(colHeader, RIGHT); } else { return null; } diff --git a/cli/src/main/java/haveno/cli/table/builder/TransactionTableBuilder.java b/cli/src/main/java/haveno/cli/table/builder/TransactionTableBuilder.java index a07b135ccd8..e6d82d05aba 100644 --- a/cli/src/main/java/haveno/cli/table/builder/TransactionTableBuilder.java +++ b/cli/src/main/java/haveno/cli/table/builder/TransactionTableBuilder.java @@ -21,7 +21,7 @@ import haveno.cli.table.column.BooleanColumn; import haveno.cli.table.column.Column; import haveno.cli.table.column.LongColumn; -import haveno.cli.table.column.SatoshiColumn; +import haveno.cli.table.column.PiconeroColumn; import haveno.cli.table.column.StringColumn; import javax.annotation.Nullable; @@ -52,9 +52,9 @@ class TransactionTableBuilder extends AbstractTableBuilder { super(TRANSACTION_TBL, protos); this.colTxId = new StringColumn(COL_HEADER_TX_ID); this.colIsConfirmed = new BooleanColumn(COL_HEADER_TX_IS_CONFIRMED); - this.colInputSum = new SatoshiColumn(COL_HEADER_TX_INPUT_SUM); - this.colOutputSum = new SatoshiColumn(COL_HEADER_TX_OUTPUT_SUM); - this.colTxFee = new SatoshiColumn(COL_HEADER_TX_FEE); + this.colInputSum = new PiconeroColumn(COL_HEADER_TX_INPUT_SUM); + this.colOutputSum = new PiconeroColumn(COL_HEADER_TX_OUTPUT_SUM); + this.colTxFee = new PiconeroColumn(COL_HEADER_TX_FEE); this.colTxSize = new LongColumn(COL_HEADER_TX_SIZE); } diff --git a/cli/src/main/java/haveno/cli/table/builder/XmrBalanceTableBuilder.java b/cli/src/main/java/haveno/cli/table/builder/XmrBalanceTableBuilder.java new file mode 100644 index 00000000000..f370794b8bd --- /dev/null +++ b/cli/src/main/java/haveno/cli/table/builder/XmrBalanceTableBuilder.java @@ -0,0 +1,47 @@ +package haveno.cli.table.builder; + +import haveno.cli.table.Table; +import haveno.cli.table.column.Column; +import haveno.cli.table.column.PiconeroColumn; +import haveno.proto.grpc.XmrBalanceInfo; + +import java.util.List; + +import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_AVAILABLE_BALANCE; +import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_LOCKED_BALANCE; +import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_RESERVED_BALANCE; +import static haveno.cli.table.builder.TableBuilderConstants.COL_HEADER_TOTAL_AVAILABLE_BALANCE; +import static haveno.cli.table.builder.TableType.XMR_BALANCE_TBL; + +public class XmrBalanceTableBuilder extends AbstractTableBuilder { + + private final Column colAvailableBalance; + private final Column colReservedBalance; + private final Column colTotalAvailableBalance; + private final Column colLockedBalance; + + public XmrBalanceTableBuilder(List protos) { + super(XMR_BALANCE_TBL, protos); + this.colAvailableBalance = new PiconeroColumn(COL_HEADER_AVAILABLE_BALANCE); + this.colReservedBalance = new PiconeroColumn(COL_HEADER_RESERVED_BALANCE); + this.colTotalAvailableBalance = new PiconeroColumn(COL_HEADER_TOTAL_AVAILABLE_BALANCE); + this.colLockedBalance = new PiconeroColumn(COL_HEADER_LOCKED_BALANCE); + } + + @Override + public Table build() { + XmrBalanceInfo balance = (XmrBalanceInfo) protos.get(0); + + // Populate columns with xmr balance info. + colAvailableBalance.addRow(balance.getAvailableBalance()); + colReservedBalance.addRow(balance.getReservedOfferBalance() + balance.getReservedTradeBalance()); + colTotalAvailableBalance.addRow(balance.getAvailableBalance() + balance.getReservedOfferBalance() + balance.getReservedTradeBalance()); + colLockedBalance.addRow(balance.getBalance() - balance.getAvailableBalance() - balance.getPendingBalance()); + + // Define and return the table instance with populated columns. + return new Table(colAvailableBalance.asStringColumn(), + colReservedBalance.asStringColumn(), + colTotalAvailableBalance.asStringColumn(), + colLockedBalance.asStringColumn()); + } +} diff --git a/cli/src/main/java/haveno/cli/table/column/MixedTradeFeeColumn.java b/cli/src/main/java/haveno/cli/table/column/MixedTradeFeeColumn.java index 4e54759ecaf..51ffcf4e1bf 100644 --- a/cli/src/main/java/haveno/cli/table/column/MixedTradeFeeColumn.java +++ b/cli/src/main/java/haveno/cli/table/column/MixedTradeFeeColumn.java @@ -17,12 +17,11 @@ package haveno.cli.table.column; -import static haveno.cli.CurrencyFormat.formatBsq; -import static haveno.cli.CurrencyFormat.formatSatoshis; +import static haveno.cli.CurrencyFormat.formatPiconeros; import static haveno.cli.table.column.Column.JUSTIFICATION.RIGHT; /** - * For displaying a mix of BSQ and BTC trade fees with appropriate precision. + * For displaying Monero trade fees with appropriate precision. */ public class MixedTradeFeeColumn extends LongColumn { @@ -32,15 +31,9 @@ public MixedTradeFeeColumn(String name) { @Override public void addRow(Long value) { - throw new UnsupportedOperationException("use public void addRow(Long value, boolean isBsq) instead"); - } - - public void addRow(Long value, boolean isBsq) { rows.add(value); - String s = isBsq - ? formatBsq(value) + " BSQ" - : formatSatoshis(value) + " BTC"; + String s = formatPiconeros(value) + " XMR"; stringColumn.addRow(s); if (isNewMaxWidth.test(s)) diff --git a/cli/src/main/java/haveno/cli/table/column/SatoshiColumn.java b/cli/src/main/java/haveno/cli/table/column/PiconeroColumn.java similarity index 57% rename from cli/src/main/java/haveno/cli/table/column/SatoshiColumn.java rename to cli/src/main/java/haveno/cli/table/column/PiconeroColumn.java index 767e878d57f..ff83cfaaa2a 100644 --- a/cli/src/main/java/haveno/cli/table/column/SatoshiColumn.java +++ b/cli/src/main/java/haveno/cli/table/column/PiconeroColumn.java @@ -17,33 +17,21 @@ package haveno.cli.table.column; -import static haveno.cli.CurrencyFormat.formatBsq; -import static haveno.cli.CurrencyFormat.formatSatoshis; +import static haveno.cli.CurrencyFormat.formatPiconeros; import static haveno.cli.table.column.Column.JUSTIFICATION.RIGHT; /** - * For displaying BTC or BSQ satoshi values with appropriate precision. + * For displaying XMR or Piconero values with appropriate precision. */ -public class SatoshiColumn extends LongColumn { +public class PiconeroColumn extends LongColumn { - protected final boolean isBsqSatoshis; - - // The default SatoshiColumn JUSTIFICATION is RIGHT. - public SatoshiColumn(String name) { - this(name, RIGHT, false); - } - - public SatoshiColumn(String name, boolean isBsqSatoshis) { - this(name, RIGHT, isBsqSatoshis); - } - - public SatoshiColumn(String name, JUSTIFICATION justification) { - this(name, justification, false); + // The default PiconeroColumn JUSTIFICATION is RIGHT. + public PiconeroColumn(String name) { + this(name, RIGHT); } - public SatoshiColumn(String name, JUSTIFICATION justification, boolean isBsqSatoshis) { + public PiconeroColumn(String name, JUSTIFICATION justification) { super(name, justification); - this.isBsqSatoshis = isBsqSatoshis; } @Override @@ -51,7 +39,7 @@ public void addRow(Long value) { rows.add(value); // We do not know how much padding each StringColumn value needs until it has all the values. - String s = isBsqSatoshis ? formatBsq(value) : formatSatoshis(value); + String s = formatPiconeros(value); stringColumn.addRow(s); if (isNewMaxWidth.test(s)) @@ -60,9 +48,7 @@ public void addRow(Long value) { @Override public String getRowAsFormattedString(int rowIndex) { - return isBsqSatoshis - ? formatBsq(getRow(rowIndex)) - : formatSatoshis(getRow(rowIndex)); + return formatPiconeros(getRow(rowIndex)); } @Override diff --git a/cli/src/main/java/haveno/cli/table/column/BtcColumn.java b/cli/src/main/java/haveno/cli/table/column/XmrColumn.java similarity index 63% rename from cli/src/main/java/haveno/cli/table/column/BtcColumn.java rename to cli/src/main/java/haveno/cli/table/column/XmrColumn.java index f0b6f779ebc..5c23c0db419 100644 --- a/cli/src/main/java/haveno/cli/table/column/BtcColumn.java +++ b/cli/src/main/java/haveno/cli/table/column/XmrColumn.java @@ -3,12 +3,12 @@ import java.util.stream.IntStream; import static com.google.common.base.Strings.padEnd; -import static haveno.cli.CurrencyFormat.formatBtc; +import static haveno.cli.CurrencyFormat.formatXmr; import static java.util.Comparator.comparingInt; -public class BtcColumn extends SatoshiColumn { +public class XmrColumn extends PiconeroColumn { - public BtcColumn(String name) { + public XmrColumn(String name) { super(name); } @@ -16,7 +16,7 @@ public BtcColumn(String name) { public void addRow(Long value) { rows.add(value); - String s = formatBtc(value); + String s = formatXmr(value); stringColumn.addRow(s); if (isNewMaxWidth.test(s)) @@ -25,22 +25,22 @@ public void addRow(Long value) { @Override public String getRowAsFormattedString(int rowIndex) { - return formatBtc(getRow(rowIndex)); + return formatXmr(getRow(rowIndex)); } @Override public StringColumn asStringColumn() { - // We cached the formatted satoshi strings, but we did + // We cached the formatted piconero strings, but we did // not know how much zero padding each string needed until now. int maxColumnValueWidth = stringColumn.getRows().stream() .max(comparingInt(String::length)) .get() .length(); IntStream.range(0, stringColumn.getRows().size()).forEach(rowIndex -> { - String btcString = stringColumn.getRow(rowIndex); - if (btcString.length() < maxColumnValueWidth) { - String paddedBtcString = padEnd(btcString, maxColumnValueWidth, '0'); - stringColumn.updateRow(rowIndex, paddedBtcString); + String xmrString = stringColumn.getRow(rowIndex); + if (xmrString.length() < maxColumnValueWidth) { + String paddedXmrString = padEnd(xmrString, maxColumnValueWidth, '0'); + stringColumn.updateRow(rowIndex, paddedXmrString); } }); return stringColumn.justify();