diff --git a/cli/src/main/java/bisq/cli/CliMain.java b/cli/src/main/java/bisq/cli/CliMain.java index 93db258fdd..31e2d34df4 100644 --- a/cli/src/main/java/bisq/cli/CliMain.java +++ b/cli/src/main/java/bisq/cli/CliMain.java @@ -72,6 +72,7 @@ import bisq.cli.opts.GetPaymentAcctFormOptionParser; import bisq.cli.opts.GetTradeOptionParser; import bisq.cli.opts.GetTradesOptionParser; import bisq.cli.opts.GetTransactionOptionParser; +import bisq.cli.opts.GetTransactionsOptionParser; import bisq.cli.opts.OfferIdOptionParser; import bisq.cli.opts.RegisterDisputeAgentOptionParser; import bisq.cli.opts.RemoveWalletPasswordOptionParser; @@ -346,6 +347,16 @@ public class CliMain { out.println(formatTxFeeRateInfo(txFeeRate)); return; } + case gettransactions: { + var opts = new GetTransactionsOptionParser(args).parse(); + if (opts.isForHelp()) { + out.println(client.getMethodHelp(method)); + return; + } + var txs = client.getTransactions(); + new TableBuilder(TRANSACTION_TBL, txs).build().print(out); + return; + } case gettransaction: { var opts = new GetTransactionOptionParser(args).parse(); if (opts.isForHelp()) { diff --git a/cli/src/main/java/bisq/cli/GrpcClient.java b/cli/src/main/java/bisq/cli/GrpcClient.java index ad073f6e31..51e25db49f 100644 --- a/cli/src/main/java/bisq/cli/GrpcClient.java +++ b/cli/src/main/java/bisq/cli/GrpcClient.java @@ -147,6 +147,10 @@ public final class GrpcClient { return walletsServiceRequest.unsetTxFeeRate(); } + public List getTransactions() { + return walletsServiceRequest.getTransactions(); + } + public TxInfo getTransaction(String txId) { return walletsServiceRequest.getTransaction(txId); } diff --git a/cli/src/main/java/bisq/cli/Method.java b/cli/src/main/java/bisq/cli/Method.java index cc410bd2e4..a310901148 100644 --- a/cli/src/main/java/bisq/cli/Method.java +++ b/cli/src/main/java/bisq/cli/Method.java @@ -47,6 +47,7 @@ public enum Method { gettrades, failtrade, unfailtrade, + gettransactions, gettransaction, gettxfeerate, getunusedbsqaddress, diff --git a/cli/src/main/java/bisq/cli/opts/GetTransactionsOptionParser.java b/cli/src/main/java/bisq/cli/opts/GetTransactionsOptionParser.java new file mode 100644 index 0000000000..d78cf24087 --- /dev/null +++ b/cli/src/main/java/bisq/cli/opts/GetTransactionsOptionParser.java @@ -0,0 +1,34 @@ +/* + * 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.opts; + +public class GetTransactionsOptionParser extends AbstractMethodOptionParser implements MethodOpts { + + public GetTransactionsOptionParser(String[] args) { + super(args); + } + + public GetTransactionsOptionParser parse() { + super.parse(); + + // Short circuit opt validation if user just wants help. + if (options.has(helpOpt)) + return this; + return this; + } +} diff --git a/cli/src/main/java/bisq/cli/request/WalletsServiceRequest.java b/cli/src/main/java/bisq/cli/request/WalletsServiceRequest.java index f3e3aee70d..df772e35dc 100644 --- a/cli/src/main/java/bisq/cli/request/WalletsServiceRequest.java +++ b/cli/src/main/java/bisq/cli/request/WalletsServiceRequest.java @@ -26,6 +26,7 @@ import bisq.proto.grpc.GetBalancesRequest; import bisq.proto.grpc.GetFundingAddressesRequest; import bisq.proto.grpc.GetNetworkRequest; import bisq.proto.grpc.GetTransactionRequest; +import bisq.proto.grpc.GetTransactionsRequest; import bisq.proto.grpc.GetTxFeeRateRequest; import bisq.proto.grpc.GetUnusedBsqAddressRequest; import bisq.proto.grpc.LockWalletRequest; @@ -158,6 +159,12 @@ public class WalletsServiceRequest { return grpcStubs.walletsService.unsetTxFeeRatePreference(request).getTxFeeRateInfo(); } + public List getTransactions() { + var request = GetTransactionsRequest.newBuilder() + .build(); + return grpcStubs.walletsService.getTransactions(request).getTxInfoList(); + } + public TxInfo getTransaction(String txId) { var request = GetTransactionRequest.newBuilder() .setTxId(txId) diff --git a/cli/src/main/java/bisq/cli/table/builder/TransactionTableBuilder.java b/cli/src/main/java/bisq/cli/table/builder/TransactionTableBuilder.java index 7227b144ab..df22c6f2a6 100644 --- a/cli/src/main/java/bisq/cli/table/builder/TransactionTableBuilder.java +++ b/cli/src/main/java/bisq/cli/table/builder/TransactionTableBuilder.java @@ -20,8 +20,7 @@ package bisq.cli.table.builder; import bisq.proto.grpc.TxInfo; import java.util.List; - -import javax.annotation.Nullable; +import java.util.stream.Collectors; import static bisq.cli.table.builder.TableBuilderConstants.*; import static bisq.cli.table.builder.TableType.TRANSACTION_TBL; @@ -47,6 +46,7 @@ class TransactionTableBuilder extends AbstractTableBuilder { private final Column colOutputSum; private final Column colTxFee; private final Column colTxSize; + private final Column colMemo; TransactionTableBuilder(List protos) { super(TRANSACTION_TBL, protos); @@ -56,32 +56,20 @@ class TransactionTableBuilder extends AbstractTableBuilder { this.colOutputSum = new SatoshiColumn(COL_HEADER_TX_OUTPUT_SUM); this.colTxFee = new SatoshiColumn(COL_HEADER_TX_FEE); this.colTxSize = new LongColumn(COL_HEADER_TX_SIZE); + this.colMemo = new StringColumn(COL_HEADER_TX_MEMO); } public Table build() { - // TODO Add 'gettransactions' api method & show multiple tx in the console. - // For now, a tx tbl is only one row. - TxInfo tx = (TxInfo) protos.get(0); - - // Declare the columns derived from tx info. - - @Nullable - Column colMemo = tx.getMemo().isEmpty() - ? null - : new StringColumn(COL_HEADER_TX_MEMO); - - // Populate columns with tx info. - - colTxId.addRow(tx.getTxId()); - colIsConfirmed.addRow(!tx.getIsPending()); - colInputSum.addRow(tx.getInputSum()); - colOutputSum.addRow(tx.getOutputSum()); - colTxFee.addRow(tx.getFee()); - colTxSize.addRow((long) tx.getSize()); - if (colMemo != null) + protos.stream().forEach(p -> { + TxInfo tx = (TxInfo) p; + colTxId.addRow(tx.getTxId()); + colIsConfirmed.addRow(!tx.getIsPending()); + colInputSum.addRow(tx.getInputSum()); + colOutputSum.addRow(tx.getOutputSum()); + colTxFee.addRow(tx.getFee()); + colTxSize.addRow((long) tx.getSize()); colMemo.addRow(tx.getMemo()); - - // Define and return the table instance with populated columns. + }); if (colMemo != null) { return new Table(colTxId, diff --git a/core/src/main/java/bisq/core/api/CoreApi.java b/core/src/main/java/bisq/core/api/CoreApi.java index 9dba6f109d..859accc4be 100644 --- a/core/src/main/java/bisq/core/api/CoreApi.java +++ b/core/src/main/java/bisq/core/api/CoreApi.java @@ -430,6 +430,10 @@ public class CoreApi { return walletsService.getMostRecentTxFeeRateInfo(); } + public Set getTransactions() { + return walletsService.getTransactions(); + } + public Transaction getTransaction(String txId) { return walletsService.getTransaction(txId); } diff --git a/core/src/main/java/bisq/core/api/CoreWalletsService.java b/core/src/main/java/bisq/core/api/CoreWalletsService.java index 204a9e44a9..efbe471ecd 100644 --- a/core/src/main/java/bisq/core/api/CoreWalletsService.java +++ b/core/src/main/java/bisq/core/api/CoreWalletsService.java @@ -81,6 +81,7 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import lombok.extern.slf4j.Slf4j; @@ -413,6 +414,10 @@ class CoreWalletsService { feeService.getLastRequest()); } + Set getTransactions() { + return btcWalletService.getTransactions(false); + } + Transaction getTransaction(String txId) { return getTransactionWithId(txId); } diff --git a/core/src/main/resources/help/gettransactions-help.txt b/core/src/main/resources/help/gettransactions-help.txt new file mode 100644 index 0000000000..20291cec8a --- /dev/null +++ b/core/src/main/resources/help/gettransactions-help.txt @@ -0,0 +1,21 @@ +gettransactions + +NAME +---- +gettransactions - get transactions + +SYNOPSIS +-------- +gettransactions + +DESCRIPTION +----------- +Returns list of a BTC transaction created by the Bisq server. + +To see full transaction details, use a bitcoin-core client or an online block explorer. + + +EXAMPLES +-------- +To see all of the transactions: +$ ./bisq-cli --password=xyz --port=9998 gettransactions diff --git a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java index 986015ea90..a9216a3411 100644 --- a/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java +++ b/daemon/src/main/java/bisq/daemon/grpc/GrpcWalletsService.java @@ -33,6 +33,8 @@ import bisq.proto.grpc.GetNetworkReply; import bisq.proto.grpc.GetNetworkRequest; import bisq.proto.grpc.GetTransactionReply; import bisq.proto.grpc.GetTransactionRequest; +import bisq.proto.grpc.GetTransactionsReply; +import bisq.proto.grpc.GetTransactionsRequest; import bisq.proto.grpc.GetTxFeeRateReply; import bisq.proto.grpc.GetTxFeeRateRequest; import bisq.proto.grpc.GetUnusedBsqAddressReply; @@ -68,6 +70,7 @@ import com.google.common.util.concurrent.FutureCallback; import java.util.HashMap; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; @@ -308,6 +311,24 @@ class GrpcWalletsService extends WalletsImplBase { } } + @Override + public void getTransactions(GetTransactionsRequest req, + StreamObserver responseObserver) { + try { + Set transactions = coreApi.getTransactions(); + log.info("Transactions count: " + transactions.size()); + var reply = GetTransactionsReply.newBuilder() + .addAllTxInfo(transactions.stream() + .map(tx -> toTxInfo(tx).toProtoMessage()) + .collect(Collectors.toList())) + .build(); + responseObserver.onNext(reply); + responseObserver.onCompleted(); + } catch (Throwable cause) { + exceptionHandler.handleException(log, cause, responseObserver); + } + } + @Override public void getTransaction(GetTransactionRequest req, StreamObserver responseObserver) { diff --git a/proto/src/main/proto/grpc.proto b/proto/src/main/proto/grpc.proto index 9363457fb6..c4da4756fb 100644 --- a/proto/src/main/proto/grpc.proto +++ b/proto/src/main/proto/grpc.proto @@ -761,6 +761,10 @@ service Wallets { // Remove the custom bitcoin miner transaction fee rate; revert to the Bisq network's bitcoin miner transaction fee rate. rpc UnsetTxFeeRatePreference (UnsetTxFeeRatePreferenceRequest) returns (UnsetTxFeeRatePreferenceReply) { } + // Get a bitcoin transactions. + rpc GetTransactions (GetTransactionsRequest) returns (GetTransactionsReply) { + } + // Get a bitcoin transaction summary. rpc GetTransaction (GetTransactionRequest) returns (GetTransactionReply) { } @@ -880,6 +884,13 @@ message UnsetTxFeeRatePreferenceReply { TxFeeRateInfo tx_fee_rate_info = 1; // The summary of the most recently available bitcoin transaction fee rates. } +message GetTransactionsRequest { +} + +message GetTransactionsReply { + repeated TxInfo tx_info = 1; // List of Bitcoin transactions. +} + message GetTransactionRequest { string tx_id = 1; }