mirror of
https://github.com/boldsuck/haveno.git
synced 2024-12-22 20:19:21 +00:00
Add API functions to get wallet transfers and withdraw funds
This commit is contained in:
parent
8dc4f63ca8
commit
c1699795e7
9 changed files with 663 additions and 16 deletions
|
@ -54,6 +54,11 @@ import java.util.function.Consumer;
|
|||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
|
||||
|
||||
import monero.wallet.model.MoneroDestination;
|
||||
import monero.wallet.model.MoneroTxWallet;
|
||||
|
||||
/**
|
||||
* Provides high level interface to functionality of core Bisq features.
|
||||
* E.g. useful for different APIs to access data of different domains of Bisq.
|
||||
|
@ -295,6 +300,18 @@ public class CoreApi {
|
|||
return walletsService.getNewDepositSubaddress();
|
||||
}
|
||||
|
||||
public List<MoneroTxWallet> getXmrTxs() {
|
||||
return walletsService.getXmrTxs();
|
||||
}
|
||||
|
||||
public MoneroTxWallet createXmrTx(List<MoneroDestination> destinations) {
|
||||
return walletsService.createXmrTx(destinations);
|
||||
}
|
||||
|
||||
public String relayXmrTx(String metadata) {
|
||||
return walletsService.relayXmrTx(metadata);
|
||||
}
|
||||
|
||||
public long getAddressBalance(String addressString) {
|
||||
return walletsService.getAddressBalance(addressString);
|
||||
}
|
||||
|
|
|
@ -26,12 +26,9 @@ import bisq.core.app.AppStartupState;
|
|||
import bisq.core.btc.Balances;
|
||||
import bisq.core.btc.exceptions.AddressEntryException;
|
||||
import bisq.core.btc.exceptions.InsufficientFundsException;
|
||||
import bisq.core.btc.exceptions.TransactionVerificationException;
|
||||
import bisq.core.btc.exceptions.WalletException;
|
||||
import bisq.core.btc.model.AddressEntry;
|
||||
import bisq.core.btc.setup.WalletsSetup;
|
||||
import bisq.core.btc.wallet.BtcWalletService;
|
||||
import bisq.core.btc.wallet.TxBroadcaster;
|
||||
import bisq.core.btc.wallet.WalletsManager;
|
||||
import bisq.core.btc.wallet.XmrWalletService;
|
||||
import bisq.core.provider.fee.FeeService;
|
||||
|
@ -47,11 +44,9 @@ import bisq.common.util.Utilities;
|
|||
import org.bitcoinj.core.Address;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.InsufficientMoneyException;
|
||||
import org.bitcoinj.core.LegacyAddress;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
import org.bitcoinj.core.TransactionConfidence;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.crypto.KeyCrypterScrypt;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
@ -73,7 +68,6 @@ import java.util.List;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
@ -85,6 +79,11 @@ import static bisq.core.util.ParsingUtils.parseToCoin;
|
|||
import static java.lang.String.format;
|
||||
import static java.util.concurrent.TimeUnit.SECONDS;
|
||||
|
||||
|
||||
|
||||
import monero.wallet.model.MoneroDestination;
|
||||
import monero.wallet.model.MoneroTxWallet;
|
||||
|
||||
@Singleton
|
||||
@Slf4j
|
||||
class CoreWalletsService {
|
||||
|
@ -157,11 +156,37 @@ class CoreWalletsService {
|
|||
return new BalancesInfo(getBtcBalances(), getXmrBalances());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String getNewDepositSubaddress() {
|
||||
return xmrWalletService.getWallet().createSubaddress(0).getAddress();
|
||||
}
|
||||
|
||||
List<MoneroTxWallet> getXmrTxs(){
|
||||
return xmrWalletService.getWallet().getTxs();
|
||||
}
|
||||
|
||||
MoneroTxWallet createXmrTx(List<MoneroDestination> destinations) {
|
||||
verifyWalletsAreAvailable();
|
||||
verifyEncryptedWalletIsUnlocked();
|
||||
try {
|
||||
return xmrWalletService.createTx(destinations);
|
||||
} catch (Exception ex) {
|
||||
log.error("", ex);
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
String relayXmrTx(String metadata) {
|
||||
verifyWalletsAreAvailable();
|
||||
verifyEncryptedWalletIsUnlocked();
|
||||
try {
|
||||
return xmrWalletService.getWallet().relayTx(metadata);
|
||||
} catch (Exception ex) {
|
||||
log.error("", ex);
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
long getAddressBalance(String addressString) {
|
||||
Address address = getAddressEntry(addressString).getAddress();
|
||||
return btcWalletService.getBalanceForAddress(address).value;
|
||||
|
@ -215,7 +240,6 @@ class CoreWalletsService {
|
|||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
||||
void sendBtc(String address,
|
||||
String amount,
|
||||
String txFeeRate,
|
||||
|
@ -530,15 +554,15 @@ class CoreWalletsService {
|
|||
var availableBalance = balances.getAvailableBalance().get();
|
||||
if (availableBalance == null)
|
||||
throw new IllegalStateException("available balance is not yet available");
|
||||
|
||||
|
||||
var lockedBalance = balances.getLockedBalance().get();
|
||||
if (lockedBalance == null)
|
||||
throw new IllegalStateException("locked balance is not yet available");
|
||||
|
||||
|
||||
var reservedOfferBalance = balances.getReservedOfferBalance().get();
|
||||
if (reservedOfferBalance == null)
|
||||
throw new IllegalStateException("reserved offer balance is not yet available");
|
||||
|
||||
|
||||
var reservedTradeBalance = balances.getReservedTradeBalance().get();
|
||||
if (reservedTradeBalance == null)
|
||||
throw new IllegalStateException("reserved trade balance is not yet available");
|
||||
|
|
69
core/src/main/java/bisq/core/api/model/XmrDestination.java
Normal file
69
core/src/main/java/bisq/core/api/model/XmrDestination.java
Normal file
|
@ -0,0 +1,69 @@
|
|||
package bisq.core.api.model;
|
||||
|
||||
import bisq.common.Payload;
|
||||
import java.math.BigInteger;
|
||||
import lombok.Getter;
|
||||
import monero.wallet.model.MoneroDestination;
|
||||
|
||||
@Getter
|
||||
public class XmrDestination implements Payload {
|
||||
|
||||
private final String address;
|
||||
private final BigInteger amount;
|
||||
|
||||
public XmrDestination(XmrDestinationBuilder builder) {
|
||||
this.address = builder.address;
|
||||
this.amount = builder.amount;
|
||||
}
|
||||
|
||||
public static XmrDestination toXmrDestination(MoneroDestination dst) {
|
||||
return new XmrDestinationBuilder()
|
||||
.withAddress(dst.getAddress())
|
||||
.withAmount(dst.getAmount())
|
||||
.build();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public bisq.proto.grpc.XmrDestination toProtoMessage() {
|
||||
return bisq.proto.grpc.XmrDestination.newBuilder()
|
||||
.setAddress(address)
|
||||
.setAmount(amount.toString())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static XmrDestination fromProto(bisq.proto.grpc.XmrDestination proto) {
|
||||
return new XmrDestinationBuilder()
|
||||
.withAddress(proto.getAddress())
|
||||
.withAmount(new BigInteger(proto.getAmount()))
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class XmrDestinationBuilder {
|
||||
private String address;
|
||||
private BigInteger amount;
|
||||
|
||||
public XmrDestinationBuilder withAddress(String address) {
|
||||
this.address = address;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrDestinationBuilder withAmount(BigInteger amount) {
|
||||
this.amount = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrDestination build() { return new XmrDestination(this); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XmrDestination{" +
|
||||
"address=" + address +
|
||||
", amount" + amount +
|
||||
'}';
|
||||
}
|
||||
}
|
107
core/src/main/java/bisq/core/api/model/XmrIncomingTransfer.java
Normal file
107
core/src/main/java/bisq/core/api/model/XmrIncomingTransfer.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
package bisq.core.api.model;
|
||||
|
||||
import bisq.common.Payload;
|
||||
import java.math.BigInteger;
|
||||
import lombok.Getter;
|
||||
import monero.wallet.model.MoneroIncomingTransfer;
|
||||
|
||||
@Getter
|
||||
public class XmrIncomingTransfer implements Payload {
|
||||
|
||||
private final BigInteger amount;
|
||||
private final Integer accountIndex;
|
||||
private final Integer subaddressIndex;
|
||||
private final String address;
|
||||
private final Long numSuggestedConfirmations;
|
||||
|
||||
public XmrIncomingTransfer(XmrIncomingTransferBuilder builder) {
|
||||
this.amount = builder.amount;
|
||||
this.accountIndex = builder.accountIndex;
|
||||
this.subaddressIndex = builder.subaddressIndex;
|
||||
this.address = builder.address;
|
||||
this.numSuggestedConfirmations = builder.numSuggestedConfirmations;
|
||||
}
|
||||
|
||||
public static XmrIncomingTransfer toXmrIncomingTransfer(MoneroIncomingTransfer transfer) {
|
||||
return new XmrIncomingTransferBuilder()
|
||||
.withAmount(transfer.getAmount())
|
||||
.withAccountIndex(transfer.getAccountIndex())
|
||||
.withSubaddressIndex(transfer.getSubaddressIndex())
|
||||
.withAddress(transfer.getAddress())
|
||||
.withNumSuggestedConfirmations(transfer.getNumSuggestedConfirmations())
|
||||
.build();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public bisq.proto.grpc.XmrIncomingTransfer toProtoMessage() {
|
||||
return bisq.proto.grpc.XmrIncomingTransfer.newBuilder()
|
||||
.setAmount(amount.toString())
|
||||
.setAccountIndex(accountIndex)
|
||||
.setSubaddressIndex(subaddressIndex)
|
||||
.setAddress(address)
|
||||
.setNumSuggestedConfirmations(numSuggestedConfirmations)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static XmrIncomingTransfer fromProto(bisq.proto.grpc.XmrIncomingTransfer proto) {
|
||||
return new XmrIncomingTransferBuilder()
|
||||
.withAmount(new BigInteger(proto.getAmount()))
|
||||
.withAccountIndex(proto.getAccountIndex())
|
||||
.withSubaddressIndex(proto.getSubaddressIndex())
|
||||
.withAddress(proto.getAddress())
|
||||
.withNumSuggestedConfirmations(proto.getNumSuggestedConfirmations())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class XmrIncomingTransferBuilder {
|
||||
private BigInteger amount;
|
||||
private Integer accountIndex;
|
||||
private Integer subaddressIndex;
|
||||
private String address;
|
||||
private Long numSuggestedConfirmations;
|
||||
|
||||
public XmrIncomingTransferBuilder withAmount(BigInteger amount) {
|
||||
this.amount = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrIncomingTransferBuilder withAccountIndex(Integer accountIndex) {
|
||||
this.accountIndex = accountIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrIncomingTransferBuilder withSubaddressIndex(Integer subaddressIndex) {
|
||||
this.subaddressIndex = subaddressIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrIncomingTransferBuilder withAddress(String address) {
|
||||
this.address = address;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrIncomingTransferBuilder withNumSuggestedConfirmations(Long numSuggestedConfirmations) {
|
||||
this.numSuggestedConfirmations = numSuggestedConfirmations;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrIncomingTransfer build() {
|
||||
return new XmrIncomingTransfer(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XmrIncomingTransfer{" +
|
||||
"amount=" + amount +
|
||||
", accountIndex=" + accountIndex +
|
||||
", subaddressIndex=" + subaddressIndex +
|
||||
", address=" + address +
|
||||
", numSuggestedConfirmations=" + numSuggestedConfirmations +
|
||||
'}';
|
||||
}
|
||||
}
|
111
core/src/main/java/bisq/core/api/model/XmrOutgoingTransfer.java
Normal file
111
core/src/main/java/bisq/core/api/model/XmrOutgoingTransfer.java
Normal file
|
@ -0,0 +1,111 @@
|
|||
package bisq.core.api.model;
|
||||
|
||||
import static bisq.core.api.model.XmrDestination.toXmrDestination;
|
||||
|
||||
import bisq.common.Payload;
|
||||
import bisq.common.proto.ProtoUtil;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import monero.wallet.model.MoneroOutgoingTransfer;
|
||||
|
||||
@Getter
|
||||
public class XmrOutgoingTransfer implements Payload {
|
||||
|
||||
private final BigInteger amount;
|
||||
private final Integer accountIndex;
|
||||
@Nullable
|
||||
private final List<Integer> subaddressIndices;
|
||||
@Nullable
|
||||
private final List<XmrDestination> destinations;
|
||||
|
||||
public XmrOutgoingTransfer(XmrOutgoingTransferBuilder builder) {
|
||||
this.amount = builder.amount;
|
||||
this.accountIndex = builder.accountIndex;
|
||||
this.subaddressIndices = builder.subaddressIndices;
|
||||
this.destinations = builder.destinations;
|
||||
}
|
||||
|
||||
public static XmrOutgoingTransfer toXmrOutgoingTransfer(MoneroOutgoingTransfer transfer) {
|
||||
List<XmrDestination> destinations = transfer.getDestinations() == null ? null :
|
||||
transfer.getDestinations().stream()
|
||||
.map(s -> toXmrDestination(s))
|
||||
.collect(Collectors.toList());
|
||||
XmrOutgoingTransferBuilder builder = new XmrOutgoingTransferBuilder()
|
||||
.withAmount(transfer.getAmount())
|
||||
.withAccountIndex(transfer.getAccountIndex())
|
||||
.withSubaddressIndices(transfer.getSubaddressIndices())
|
||||
.withDestinations(destinations);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public bisq.proto.grpc.XmrOutgoingTransfer toProtoMessage() {
|
||||
var builder = bisq.proto.grpc.XmrOutgoingTransfer.newBuilder()
|
||||
.setAmount(amount.toString())
|
||||
.setAccountIndex(accountIndex);
|
||||
Optional.ofNullable(subaddressIndices).ifPresent(e -> builder.addAllSubaddressIndices(subaddressIndices));
|
||||
Optional.ofNullable(destinations).ifPresent(e -> builder.addAllDestinations(ProtoUtil.collectionToProto(destinations, bisq.proto.grpc.XmrDestination.class)));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static XmrOutgoingTransfer fromProto(bisq.proto.grpc.XmrOutgoingTransfer proto) {
|
||||
List<XmrDestination> destinations = proto.getDestinationsList().isEmpty() ?
|
||||
null : proto.getDestinationsList().stream()
|
||||
.map(XmrDestination::fromProto).collect(Collectors.toList());
|
||||
return new XmrOutgoingTransferBuilder()
|
||||
.withAmount(new BigInteger(proto.getAmount()))
|
||||
.withAccountIndex(proto.getAccountIndex())
|
||||
.withSubaddressIndices(proto.getSubaddressIndicesList())
|
||||
.withDestinations(destinations)
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class XmrOutgoingTransferBuilder {
|
||||
private BigInteger amount;
|
||||
private Integer accountIndex;
|
||||
private List<Integer> subaddressIndices;
|
||||
private List<XmrDestination> destinations;
|
||||
|
||||
public XmrOutgoingTransferBuilder withAmount(BigInteger amount) {
|
||||
this.amount = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrOutgoingTransferBuilder withAccountIndex(Integer accountIndex) {
|
||||
this.accountIndex = accountIndex;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrOutgoingTransferBuilder withSubaddressIndices(List<Integer> subaddressIndices) {
|
||||
this.subaddressIndices = subaddressIndices;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrOutgoingTransferBuilder withDestinations(List<XmrDestination> destinations) {
|
||||
this.destinations = destinations;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrOutgoingTransfer build() {
|
||||
return new XmrOutgoingTransfer(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XmrOutgoingTransfer{" +
|
||||
"amount=" + amount +
|
||||
", accountIndex=" + accountIndex +
|
||||
", subaddressIndices=" + subaddressIndices +
|
||||
", destinations=" + destinations +
|
||||
'}';
|
||||
}
|
||||
}
|
176
core/src/main/java/bisq/core/api/model/XmrTx.java
Normal file
176
core/src/main/java/bisq/core/api/model/XmrTx.java
Normal file
|
@ -0,0 +1,176 @@
|
|||
package bisq.core.api.model;
|
||||
|
||||
import static bisq.core.api.model.XmrIncomingTransfer.toXmrIncomingTransfer;
|
||||
import static bisq.core.api.model.XmrOutgoingTransfer.toXmrOutgoingTransfer;
|
||||
|
||||
import bisq.common.Payload;
|
||||
import bisq.common.proto.ProtoUtil;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.annotation.Nullable;
|
||||
import lombok.Getter;
|
||||
import monero.wallet.model.MoneroTxWallet;
|
||||
|
||||
@Getter
|
||||
public class XmrTx implements Payload {
|
||||
|
||||
private final String hash;
|
||||
private final BigInteger fee;
|
||||
private final boolean isConfirmed;
|
||||
private final boolean isLocked;
|
||||
@Nullable
|
||||
private final Long height;
|
||||
@Nullable
|
||||
private final Long timestamp;
|
||||
@Nullable
|
||||
private final List<XmrIncomingTransfer> incomingTransfers;
|
||||
@Nullable
|
||||
private final XmrOutgoingTransfer outgoingTransfer;
|
||||
@Nullable
|
||||
private final String metadata;
|
||||
|
||||
public XmrTx(XmrTxBuilder builder) {
|
||||
this.hash = builder.hash;
|
||||
this.fee = builder.fee;
|
||||
this.isConfirmed = builder.isConfirmed;
|
||||
this.isLocked = builder.isLocked;
|
||||
this.height = builder.height;
|
||||
this.timestamp = builder.timestamp;
|
||||
this.incomingTransfers = builder.incomingTransfers;
|
||||
this.outgoingTransfer = builder.outgoingTransfer;
|
||||
this.metadata = builder.metadata;
|
||||
}
|
||||
|
||||
public static XmrTx toXmrTx(MoneroTxWallet tx){
|
||||
Long timestamp = tx.getBlock() == null ? null : tx.getBlock().getTimestamp();
|
||||
List<XmrIncomingTransfer> incomingTransfers = tx.getIncomingTransfers() == null ? null :
|
||||
tx.getIncomingTransfers().stream()
|
||||
.map(s -> toXmrIncomingTransfer(s))
|
||||
.collect(Collectors.toList());
|
||||
XmrOutgoingTransfer outgoingTransfer = tx.getOutgoingTransfer() == null ? null :
|
||||
toXmrOutgoingTransfer(tx.getOutgoingTransfer());
|
||||
XmrTxBuilder builder = new XmrTxBuilder()
|
||||
.withHash(tx.getHash())
|
||||
.withFee(tx.getFee())
|
||||
.withIsConfirmed(tx.isConfirmed())
|
||||
.withIsLocked(tx.isLocked());
|
||||
Optional.ofNullable(tx.getHeight()).ifPresent(e ->builder.withHeight(tx.getHeight()));
|
||||
Optional.ofNullable(timestamp).ifPresent(e ->builder.withTimestamp(timestamp));
|
||||
Optional.ofNullable(outgoingTransfer).ifPresent(e ->builder.withOutgoingTransfer(outgoingTransfer));
|
||||
Optional.ofNullable(incomingTransfers).ifPresent(e ->builder.withIncomingTransfers(incomingTransfers));
|
||||
Optional.ofNullable(tx.getMetadata()).ifPresent(e ->builder.withMetadata(tx.getMetadata()));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public bisq.proto.grpc.XmrTx toProtoMessage() {
|
||||
bisq.proto.grpc.XmrTx.Builder builder = bisq.proto.grpc.XmrTx.newBuilder()
|
||||
.setHash(hash)
|
||||
.setFee(fee.toString())
|
||||
.setIsConfirmed(isConfirmed)
|
||||
.setIsLocked(isLocked);
|
||||
Optional.ofNullable(height).ifPresent(e -> builder.setHeight(height));
|
||||
Optional.ofNullable(timestamp).ifPresent(e -> builder.setTimestamp(timestamp));
|
||||
Optional.ofNullable(outgoingTransfer).ifPresent(e -> builder.setOutgoingTransfer(outgoingTransfer.toProtoMessage()));
|
||||
Optional.ofNullable(incomingTransfers).ifPresent(e -> builder.addAllIncomingTransfers(ProtoUtil.collectionToProto(incomingTransfers, bisq.proto.grpc.XmrIncomingTransfer.class)));
|
||||
Optional.ofNullable(metadata).ifPresent(e -> builder.setMetadata(metadata));
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public static XmrTx fromProto(bisq.proto.grpc.XmrTx proto) {
|
||||
return new XmrTxBuilder()
|
||||
.withHash(proto.getHash())
|
||||
.withFee(new BigInteger(proto.getFee()))
|
||||
.withIsConfirmed(proto.getIsConfirmed())
|
||||
.withIsLocked(proto.getIsLocked())
|
||||
.withHeight(proto.getHeight())
|
||||
.withTimestamp(proto.getTimestamp())
|
||||
.withIncomingTransfers(
|
||||
proto.getIncomingTransfersList().stream()
|
||||
.map(XmrIncomingTransfer::fromProto)
|
||||
.collect(Collectors.toList()))
|
||||
.withOutgoingTransfer(XmrOutgoingTransfer.fromProto(proto.getOutgoingTransfer()))
|
||||
.withMetadata(proto.getMetadata())
|
||||
.build();
|
||||
}
|
||||
|
||||
public static class XmrTxBuilder {
|
||||
private String hash;
|
||||
private BigInteger fee;
|
||||
private boolean isConfirmed;
|
||||
private boolean isLocked;
|
||||
private Long height;
|
||||
private Long timestamp;
|
||||
private List<XmrIncomingTransfer> incomingTransfers;
|
||||
private XmrOutgoingTransfer outgoingTransfer;
|
||||
private String metadata;
|
||||
|
||||
public XmrTxBuilder withHash(String hash) {
|
||||
this.hash = hash;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withFee(BigInteger fee) {
|
||||
this.fee = fee;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withIsConfirmed(boolean isConfirmed) {
|
||||
this.isConfirmed = isConfirmed;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withIsLocked(boolean isLocked) {
|
||||
this.isLocked = isLocked;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withHeight(Long height) {
|
||||
this.height = height;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withTimestamp(Long timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withIncomingTransfers(List<XmrIncomingTransfer> incomingTransfers) {
|
||||
this.incomingTransfers = incomingTransfers;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withOutgoingTransfer(XmrOutgoingTransfer outgoingTransfer) {
|
||||
this.outgoingTransfer = outgoingTransfer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTxBuilder withMetadata(String metadata) {
|
||||
this.metadata = metadata;
|
||||
return this;
|
||||
}
|
||||
|
||||
public XmrTx build() { return new XmrTx(this); }
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "XmrTx{" +
|
||||
"hash=" + hash +
|
||||
", fee=" + timestamp +
|
||||
", isConfirmed=" + isConfirmed +
|
||||
", isLocked=" + isLocked +
|
||||
", height=" + height +
|
||||
", timestamp=" + timestamp +
|
||||
", incomingTransfers=" + incomingTransfers +
|
||||
", outgoingTransfer=" + outgoingTransfer +
|
||||
", metadata=" + metadata +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -34,6 +34,7 @@ import lombok.Getter;
|
|||
|
||||
import monero.daemon.MoneroDaemon;
|
||||
import monero.wallet.MoneroWallet;
|
||||
import monero.wallet.model.MoneroDestination;
|
||||
import monero.wallet.model.MoneroOutputWallet;
|
||||
import monero.wallet.model.MoneroSubaddress;
|
||||
import monero.wallet.model.MoneroTxConfig;
|
||||
|
@ -239,7 +240,7 @@ public class XmrWalletService {
|
|||
}
|
||||
|
||||
public Coin getBalanceForSubaddress(int subaddressIndex) {
|
||||
|
||||
|
||||
// get subaddress balance
|
||||
BigInteger balance = wallet.getBalance(0, subaddressIndex);
|
||||
|
||||
|
@ -358,6 +359,25 @@ public class XmrWalletService {
|
|||
// return sendResult.tx.getTxId().toString();
|
||||
// }
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Create Tx
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public MoneroTxWallet createTx(List<MoneroDestination> destinations) {
|
||||
try {
|
||||
MoneroTxWallet tx = wallet.createTx(new MoneroTxConfig()
|
||||
.setAccountIndex(0)
|
||||
.setDestinations(destinations)
|
||||
.setRelay(false)
|
||||
.setCanSplit(false));
|
||||
printTxs("XmrWalletService.createTx", tx);
|
||||
return tx;
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Util
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -414,7 +434,7 @@ public class XmrWalletService {
|
|||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onBalancesChanged(BigInteger newBalance, BigInteger newUnlockedBalance) {
|
||||
UserThread.execute(new Runnable() {
|
||||
|
|
|
@ -20,8 +20,6 @@ package bisq.daemon.grpc;
|
|||
import bisq.core.api.CoreApi;
|
||||
import bisq.core.api.model.AddressBalanceInfo;
|
||||
import bisq.core.api.model.TxFeeRateInfo;
|
||||
import bisq.core.btc.exceptions.TxBroadcastException;
|
||||
import bisq.core.btc.wallet.TxBroadcaster;
|
||||
|
||||
import bisq.proto.grpc.GetAddressBalanceReply;
|
||||
import bisq.proto.grpc.GetAddressBalanceRequest;
|
||||
|
@ -31,6 +29,12 @@ import bisq.proto.grpc.GetFundingAddressesReply;
|
|||
import bisq.proto.grpc.GetFundingAddressesRequest;
|
||||
import bisq.proto.grpc.GetNewDepositSubaddressRequest;
|
||||
import bisq.proto.grpc.GetNewDepositSubaddressReply;
|
||||
import bisq.proto.grpc.GetXmrTxsRequest;
|
||||
import bisq.proto.grpc.GetXmrTxsReply;
|
||||
import bisq.proto.grpc.CreateXmrTxRequest;
|
||||
import bisq.proto.grpc.CreateXmrTxReply;
|
||||
import bisq.proto.grpc.RelayXmrTxRequest;
|
||||
import bisq.proto.grpc.RelayXmrTxReply;
|
||||
import bisq.proto.grpc.GetTransactionReply;
|
||||
import bisq.proto.grpc.GetTransactionRequest;
|
||||
import bisq.proto.grpc.GetTxFeeRateReply;
|
||||
|
@ -59,6 +63,8 @@ import javax.inject.Inject;
|
|||
|
||||
import com.google.common.util.concurrent.FutureCallback;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
@ -69,6 +75,7 @@ import lombok.extern.slf4j.Slf4j;
|
|||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static bisq.core.api.model.TxInfo.toTxInfo;
|
||||
import static bisq.core.api.model.XmrTx.toXmrTx;
|
||||
import static bisq.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
|
||||
import static bisq.proto.grpc.WalletsGrpc.*;
|
||||
import static java.util.concurrent.TimeUnit.MINUTES;
|
||||
|
@ -78,6 +85,8 @@ import static java.util.concurrent.TimeUnit.SECONDS;
|
|||
|
||||
import bisq.daemon.grpc.interceptor.CallRateMeteringInterceptor;
|
||||
import bisq.daemon.grpc.interceptor.GrpcCallRateMeter;
|
||||
import monero.wallet.model.MoneroDestination;
|
||||
import monero.wallet.model.MoneroTxWallet;
|
||||
|
||||
@Slf4j
|
||||
class GrpcWalletsService extends WalletsImplBase {
|
||||
|
@ -104,7 +113,7 @@ class GrpcWalletsService extends WalletsImplBase {
|
|||
exceptionHandler.handleException(log, cause, responseObserver);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void getNewDepositSubaddress(GetNewDepositSubaddressRequest req,
|
||||
StreamObserver<GetNewDepositSubaddressReply> responseObserver) {
|
||||
|
@ -120,6 +129,59 @@ class GrpcWalletsService extends WalletsImplBase {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getXmrTxs(GetXmrTxsRequest req, StreamObserver<GetXmrTxsReply> responseObserver) {
|
||||
try {
|
||||
List<MoneroTxWallet> xmrTxs = coreApi.getXmrTxs();
|
||||
var reply = GetXmrTxsReply.newBuilder()
|
||||
.addAllTxs(xmrTxs.stream()
|
||||
.map(s -> toXmrTx(s).toProtoMessage())
|
||||
.collect(Collectors.toList()))
|
||||
.build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
} catch (Throwable cause) {
|
||||
exceptionHandler.handleException(log, cause, responseObserver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createXmrTx(CreateXmrTxRequest req,
|
||||
StreamObserver<CreateXmrTxReply> responseObserver) {
|
||||
try {
|
||||
MoneroTxWallet tx = coreApi.createXmrTx(
|
||||
req.getDestinationsList()
|
||||
.stream()
|
||||
.map(s -> new MoneroDestination(s.getAddress(), new BigInteger(s.getAmount())))
|
||||
.collect(Collectors.toList()));
|
||||
log.info("Successfully created XMR tx: hash {}, metadata {}",
|
||||
tx.getHash(),
|
||||
tx.getMetadata());
|
||||
var reply = CreateXmrTxReply.newBuilder()
|
||||
.setTx(toXmrTx(tx).toProtoMessage())
|
||||
.build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
} catch (Throwable cause) {
|
||||
exceptionHandler.handleException(log, cause, responseObserver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void relayXmrTx(RelayXmrTxRequest req,
|
||||
StreamObserver<RelayXmrTxReply> responseObserver) {
|
||||
try {
|
||||
String txHash = coreApi.relayXmrTx(req.getMetadata());
|
||||
var reply = RelayXmrTxReply.newBuilder()
|
||||
.setHash(txHash)
|
||||
.build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
} catch (Throwable cause) {
|
||||
exceptionHandler.handleException(log, cause, responseObserver);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getAddressBalance(GetAddressBalanceRequest req,
|
||||
StreamObserver<GetAddressBalanceReply> responseObserver) {
|
||||
|
|
|
@ -453,6 +453,12 @@ service Wallets {
|
|||
}
|
||||
rpc GetNewDepositSubaddress (GetNewDepositSubaddressRequest) returns (GetNewDepositSubaddressReply) {
|
||||
}
|
||||
rpc GetXmrTxs (GetXmrTxsRequest) returns (GetXmrTxsReply) {
|
||||
}
|
||||
rpc CreateXmrTx (CreateXmrTxRequest) returns (CreateXmrTxReply) {
|
||||
}
|
||||
rpc relayXmrTx (RelayXmrTxRequest) returns (RelayXmrTxReply) {
|
||||
}
|
||||
rpc GetAddressBalance (GetAddressBalanceRequest) returns (GetAddressBalanceReply) {
|
||||
}
|
||||
rpc SendBtc (SendBtcRequest) returns (SendBtcReply) {
|
||||
|
@ -492,6 +498,61 @@ message GetNewDepositSubaddressReply {
|
|||
string subaddress = 1;
|
||||
}
|
||||
|
||||
message GetXmrTxsRequest {
|
||||
}
|
||||
|
||||
message GetXmrTxsReply {
|
||||
repeated XmrTx txs = 1;
|
||||
}
|
||||
|
||||
message XmrTx {
|
||||
string hash = 1;
|
||||
string fee = 2;
|
||||
bool is_confirmed = 3;
|
||||
bool is_locked = 4;
|
||||
uint64 height = 5;
|
||||
uint64 timestamp = 6;
|
||||
repeated XmrIncomingTransfer incoming_transfers = 7;
|
||||
XmrOutgoingTransfer outgoing_transfer = 8;
|
||||
string metadata = 9;
|
||||
}
|
||||
|
||||
message XmrDestination {
|
||||
string address = 1;
|
||||
string amount = 2;
|
||||
}
|
||||
|
||||
message XmrIncomingTransfer {
|
||||
string amount = 1;
|
||||
int32 account_index = 2;
|
||||
int32 subaddress_index = 3;
|
||||
string address = 4;
|
||||
uint64 num_suggested_confirmations = 5;
|
||||
}
|
||||
|
||||
message XmrOutgoingTransfer {
|
||||
string amount = 1;
|
||||
int32 account_index = 2;
|
||||
repeated int32 subaddress_indices = 3;
|
||||
repeated XmrDestination destinations = 4;
|
||||
}
|
||||
|
||||
message CreateXmrTxRequest {
|
||||
repeated XmrDestination destinations = 1;
|
||||
}
|
||||
|
||||
message CreateXmrTxReply {
|
||||
XmrTx tx = 1;
|
||||
}
|
||||
|
||||
message RelayXmrTxRequest {
|
||||
string metadata = 1;
|
||||
}
|
||||
|
||||
message RelayXmrTxReply {
|
||||
string hash = 1;
|
||||
}
|
||||
|
||||
message GetAddressBalanceRequest {
|
||||
string address = 1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue