support sweeping funds from grpc api, relay multiple txs

This commit is contained in:
woodser 2025-06-13 07:57:02 -04:00 committed by GitHub
parent ab5f6c8191
commit 2f18a74478
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 89 additions and 25 deletions

View file

@ -299,8 +299,12 @@ public class CoreApi {
return walletsService.createXmrTx(destinations);
}
public String relayXmrTx(String metadata) {
return walletsService.relayXmrTx(metadata);
public List<MoneroTxWallet> createXmrSweepTxs(String address) {
return walletsService.createXmrSweepTxs(address);
}
public List<String> relayXmrTxs(List<String> metadatas) {
return walletsService.relayXmrTxs(metadatas);
}
public long getAddressBalance(String addressString) {

View file

@ -173,12 +173,24 @@ class CoreWalletsService {
}
}
String relayXmrTx(String metadata) {
List<MoneroTxWallet> createXmrSweepTxs(String address) {
accountService.checkAccountOpen();
verifyWalletsAreAvailable();
verifyEncryptedWalletIsUnlocked();
try {
return xmrWalletService.relayTx(metadata);
return xmrWalletService.createSweepTxs(address);
} catch (Exception ex) {
log.error("", ex);
throw new IllegalStateException(ex);
}
}
List<String> relayXmrTxs(List<String> metadatas) {
accountService.checkAccountOpen();
verifyWalletsAreAvailable();
verifyEncryptedWalletIsUnlocked();
try {
return xmrWalletService.relayTxs(metadatas);
} catch (Exception ex) {
log.error("", ex);
throw new IllegalStateException(ex);

View file

@ -441,6 +441,12 @@ public class XmrWalletService extends XmrWalletBase {
if (name.contains(File.separator)) throw new IllegalArgumentException("Path not expected: " + name);
}
public MoneroTxWallet createTx(List<MoneroDestination> destinations) {
MoneroTxWallet tx = createTx(new MoneroTxConfig().setAccountIndex(0).setDestinations(destinations).setRelay(false).setCanSplit(false));
//printTxs("XmrWalletService.createTx", tx);
return tx;
}
public MoneroTxWallet createTx(MoneroTxConfig txConfig) {
synchronized (walletLock) {
synchronized (HavenoUtils.getWalletFunctionLock()) {
@ -455,18 +461,30 @@ public class XmrWalletService extends XmrWalletBase {
}
}
public String relayTx(String metadata) {
public List<MoneroTxWallet> createSweepTxs(String address) {
return createSweepTxs(new MoneroTxConfig().setAccountIndex(0).setAddress(address).setRelay(false));
}
public List<MoneroTxWallet> createSweepTxs(MoneroTxConfig txConfig) {
synchronized (walletLock) {
String txId = wallet.relayTx(metadata);
requestSaveWallet();
return txId;
synchronized (HavenoUtils.getWalletFunctionLock()) {
List<MoneroTxWallet> txs = wallet.sweepUnlocked(txConfig);
if (Boolean.TRUE.equals(txConfig.getRelay())) {
for (MoneroTxWallet tx : txs) cachedTxs.addFirst(tx);
cacheWalletInfo();
requestSaveWallet();
}
return txs;
}
}
}
public MoneroTxWallet createTx(List<MoneroDestination> destinations) {
MoneroTxWallet tx = createTx(new MoneroTxConfig().setAccountIndex(0).setDestinations(destinations).setRelay(false).setCanSplit(false));
//printTxs("XmrWalletService.createTx", tx);
return tx;
public List<String> relayTxs(List<String> metadatas) {
synchronized (walletLock) {
List<String> txIds = wallet.relayTxs(metadatas);
requestSaveWallet();
return txIds;
}
}
/**

View file

@ -43,6 +43,8 @@ import static haveno.core.api.model.XmrTx.toXmrTx;
import haveno.daemon.grpc.interceptor.CallRateMeteringInterceptor;
import haveno.daemon.grpc.interceptor.GrpcCallRateMeter;
import static haveno.daemon.grpc.interceptor.GrpcServiceRateMeteringConfig.getCustomRateMeteringInterceptor;
import haveno.proto.grpc.CreateXmrSweepTxsReply;
import haveno.proto.grpc.CreateXmrSweepTxsRequest;
import haveno.proto.grpc.CreateXmrTxReply;
import haveno.proto.grpc.CreateXmrTxRequest;
import haveno.proto.grpc.GetAddressBalanceReply;
@ -61,8 +63,8 @@ import haveno.proto.grpc.GetXmrTxsReply;
import haveno.proto.grpc.GetXmrTxsRequest;
import haveno.proto.grpc.LockWalletReply;
import haveno.proto.grpc.LockWalletRequest;
import haveno.proto.grpc.RelayXmrTxReply;
import haveno.proto.grpc.RelayXmrTxRequest;
import haveno.proto.grpc.RelayXmrTxsReply;
import haveno.proto.grpc.RelayXmrTxsRequest;
import haveno.proto.grpc.RemoveWalletPasswordReply;
import haveno.proto.grpc.RemoveWalletPasswordRequest;
import haveno.proto.grpc.SetWalletPasswordReply;
@ -185,7 +187,7 @@ class GrpcWalletsService extends WalletsImplBase {
.stream()
.map(s -> new MoneroDestination(s.getAddress(), new BigInteger(s.getAmount())))
.collect(Collectors.toList()));
log.info("Successfully created XMR tx: hash {}", tx.getHash());
log.info("Successfully created XMR tx, hash: {}", tx.getHash());
var reply = CreateXmrTxReply.newBuilder()
.setTx(toXmrTx(tx).toProtoMessage())
.build();
@ -197,12 +199,30 @@ class GrpcWalletsService extends WalletsImplBase {
}
@Override
public void relayXmrTx(RelayXmrTxRequest req,
StreamObserver<RelayXmrTxReply> responseObserver) {
public void createXmrSweepTxs(CreateXmrSweepTxsRequest req,
StreamObserver<CreateXmrSweepTxsReply> responseObserver) {
try {
String txHash = coreApi.relayXmrTx(req.getMetadata());
var reply = RelayXmrTxReply.newBuilder()
.setHash(txHash)
List<MoneroTxWallet> xmrTxs = coreApi.createXmrSweepTxs(req.getAddress());
log.info("Successfully created XMR sweep txs, hashes: {}", xmrTxs.stream().map(MoneroTxWallet::getHash).collect(Collectors.toList()));
var reply = CreateXmrSweepTxsReply.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 relayXmrTxs(RelayXmrTxsRequest req,
StreamObserver<RelayXmrTxsReply> responseObserver) {
try {
List<String> txHashes = coreApi.relayXmrTxs(req.getMetadatasList());
var reply = RelayXmrTxsReply.newBuilder()
.addAllHashes(txHashes)
.build();
responseObserver.onNext(reply);
responseObserver.onCompleted();

View file

@ -944,7 +944,9 @@ service Wallets {
}
rpc CreateXmrTx (CreateXmrTxRequest) returns (CreateXmrTxReply) {
}
rpc relayXmrTx (RelayXmrTxRequest) returns (RelayXmrTxReply) {
rpc CreateXmrSweepTxs (CreateXmrSweepTxsRequest) returns (CreateXmrSweepTxsReply) {
}
rpc RelayXmrTxs (RelayXmrTxsRequest) returns (RelayXmrTxsReply) {
}
rpc GetAddressBalance (GetAddressBalanceRequest) returns (GetAddressBalanceReply) {
}
@ -1036,12 +1038,20 @@ message CreateXmrTxReply {
XmrTx tx = 1;
}
message RelayXmrTxRequest {
string metadata = 1;
message CreateXmrSweepTxsRequest {
string address = 1;
}
message RelayXmrTxReply {
string hash = 1;
message CreateXmrSweepTxsReply {
repeated XmrTx txs = 1;
}
message RelayXmrTxsRequest {
repeated string metadatas = 1;
}
message RelayXmrTxsReply {
repeated string hashes = 2;
}
message GetAddressBalanceRequest {