mirror of
https://github.com/haveno-dex/haveno.git
synced 2024-12-22 19:49:32 +00:00
add grpc error handling for confirming payment sent and received
This commit is contained in:
parent
6918ecf620
commit
f61fd09127
7 changed files with 58 additions and 54 deletions
|
@ -549,18 +549,19 @@ public class CoreApi {
|
||||||
Consumer<Trade> resultHandler,
|
Consumer<Trade> resultHandler,
|
||||||
ErrorMessageHandler errorMessageHandler) {
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
Offer offer = coreOffersService.getOffer(offerId);
|
Offer offer = coreOffersService.getOffer(offerId);
|
||||||
coreTradesService.takeOffer(offer,
|
coreTradesService.takeOffer(offer, paymentAccountId, resultHandler, errorMessageHandler);
|
||||||
paymentAccountId,
|
|
||||||
resultHandler,
|
|
||||||
errorMessageHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmPaymentStarted(String tradeId) {
|
public void confirmPaymentStarted(String tradeId,
|
||||||
coreTradesService.confirmPaymentStarted(tradeId);
|
ResultHandler resultHandler,
|
||||||
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
|
coreTradesService.confirmPaymentStarted(tradeId, resultHandler, errorMessageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmPaymentReceived(String tradeId) {
|
public void confirmPaymentReceived(String tradeId,
|
||||||
coreTradesService.confirmPaymentReceived(tradeId);
|
ResultHandler resultHandler,
|
||||||
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
|
coreTradesService.confirmPaymentReceived(tradeId, resultHandler, errorMessageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void keepFunds(String tradeId) {
|
public void keepFunds(String tradeId) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ import bisq.core.user.User;
|
||||||
import bisq.core.util.validation.BtcAddressValidator;
|
import bisq.core.util.validation.BtcAddressValidator;
|
||||||
|
|
||||||
import bisq.common.handlers.ErrorMessageHandler;
|
import bisq.common.handlers.ErrorMessageHandler;
|
||||||
|
import bisq.common.handlers.ResultHandler;
|
||||||
import org.bitcoinj.core.Coin;
|
import org.bitcoinj.core.Coin;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -131,35 +131,27 @@ class CoreTradesService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmPaymentStarted(String tradeId) {
|
void confirmPaymentStarted(String tradeId,
|
||||||
|
ResultHandler resultHandler,
|
||||||
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
var trade = getTrade(tradeId);
|
var trade = getTrade(tradeId);
|
||||||
if (isFollowingBuyerProtocol(trade)) {
|
if (isFollowingBuyerProtocol(trade)) {
|
||||||
var tradeProtocol = tradeManager.getTradeProtocol(trade);
|
var tradeProtocol = tradeManager.getTradeProtocol(trade);
|
||||||
((BuyerProtocol) tradeProtocol).onPaymentStarted(
|
((BuyerProtocol) tradeProtocol).onPaymentStarted(resultHandler, errorMessageHandler);
|
||||||
() -> {
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
throw new IllegalStateException(errorMessage);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("you are the seller and not sending payment");
|
throw new IllegalStateException("you are the seller and not sending payment");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void confirmPaymentReceived(String tradeId) {
|
void confirmPaymentReceived(String tradeId,
|
||||||
|
ResultHandler resultHandler,
|
||||||
|
ErrorMessageHandler errorMessageHandler) {
|
||||||
var trade = getTrade(tradeId);
|
var trade = getTrade(tradeId);
|
||||||
if (isFollowingBuyerProtocol(trade)) {
|
if (isFollowingBuyerProtocol(trade)) {
|
||||||
throw new IllegalStateException("you are the buyer, and not receiving payment");
|
throw new IllegalStateException("you are the buyer, and not receiving payment");
|
||||||
} else {
|
} else {
|
||||||
var tradeProtocol = tradeManager.getTradeProtocol(trade);
|
var tradeProtocol = tradeManager.getTradeProtocol(trade);
|
||||||
((SellerProtocol) tradeProtocol).onPaymentReceived(
|
((SellerProtocol) tradeProtocol).onPaymentReceived(resultHandler, errorMessageHandler);
|
||||||
() -> {
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
throw new IllegalStateException(errorMessage);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -185,23 +185,21 @@ public class XmrWalletService {
|
||||||
// TODO (woodser): test retaking failed trade. create new multisig wallet or replace? cannot reuse
|
// TODO (woodser): test retaking failed trade. create new multisig wallet or replace? cannot reuse
|
||||||
public MoneroWallet createMultisigWallet(String tradeId) {
|
public MoneroWallet createMultisigWallet(String tradeId) {
|
||||||
log.info("{}.createMultisigWallet({})", getClass().getSimpleName(), tradeId);
|
log.info("{}.createMultisigWallet({})", getClass().getSimpleName(), tradeId);
|
||||||
Trade trade = tradeManager.getOpenTrade(tradeId).get();
|
if (multisigWallets.containsKey(tradeId)) return multisigWallets.get(tradeId);
|
||||||
if (multisigWallets.containsKey(trade.getId())) return multisigWallets.get(trade.getId());
|
String path = MONERO_MULTISIG_WALLET_PREFIX + tradeId;
|
||||||
String path = MONERO_MULTISIG_WALLET_PREFIX + trade.getId();
|
|
||||||
MoneroWallet multisigWallet = createWallet(new MoneroWalletConfig().setPath(path).setPassword(getWalletPassword()), null, false); // auto-assign port
|
MoneroWallet multisigWallet = createWallet(new MoneroWalletConfig().setPath(path).setPassword(getWalletPassword()), null, false); // auto-assign port
|
||||||
multisigWallets.put(trade.getId(), multisigWallet);
|
multisigWallets.put(tradeId, multisigWallet);
|
||||||
return multisigWallet;
|
return multisigWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (woodser): provide progress notifications during open?
|
// TODO (woodser): provide progress notifications during open?
|
||||||
public MoneroWallet getMultisigWallet(String tradeId) {
|
public MoneroWallet getMultisigWallet(String tradeId) {
|
||||||
log.info("{}.getMultisigWallet({})", getClass().getSimpleName(), tradeId);
|
log.info("{}.getMultisigWallet({})", getClass().getSimpleName(), tradeId);
|
||||||
Trade trade = tradeManager.getTrade(tradeId);
|
if (multisigWallets.containsKey(tradeId)) return multisigWallets.get(tradeId);
|
||||||
if (multisigWallets.containsKey(trade.getId())) return multisigWallets.get(trade.getId());
|
String path = MONERO_MULTISIG_WALLET_PREFIX + tradeId;
|
||||||
String path = MONERO_MULTISIG_WALLET_PREFIX + trade.getId();
|
if (!walletExists(path)) throw new RuntimeException("Multisig wallet does not exist for trade " + tradeId);
|
||||||
if (!walletExists(path)) throw new RuntimeException("Multisig wallet does not exist for trade " + trade.getId());
|
|
||||||
MoneroWallet multisigWallet = openWallet(new MoneroWalletConfig().setPath(path).setPassword(getWalletPassword()), null);
|
MoneroWallet multisigWallet = openWallet(new MoneroWalletConfig().setPath(path).setPassword(getWalletPassword()), null);
|
||||||
multisigWallets.put(trade.getId(), multisigWallet);
|
multisigWallets.put(tradeId, multisigWallet);
|
||||||
return multisigWallet;
|
return multisigWallet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -923,7 +923,7 @@ public abstract class Trade implements Tradable, Model {
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if deposit txs unlocked
|
// check if deposit txs unlocked
|
||||||
if (unlockHeight != null && height == unlockHeight) {
|
if (unlockHeight != null && height >= unlockHeight) {
|
||||||
log.info("Multisig deposits unlocked for trade {}", getId());
|
log.info("Multisig deposits unlocked for trade {}", getId());
|
||||||
setUnlockedState();
|
setUnlockedState();
|
||||||
xmrWalletService.removeWalletListener(depositTxListener); // remove listener when notified
|
xmrWalletService.removeWalletListener(depositTxListener); // remove listener when notified
|
||||||
|
|
|
@ -127,6 +127,8 @@ public abstract class BuyerProtocol extends DisputeProtocol {
|
||||||
public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
public void onPaymentStarted(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
System.out.println("BuyerProtocol.onPaymentStarted()");
|
System.out.println("BuyerProtocol.onPaymentStarted()");
|
||||||
synchronized (trade) {
|
synchronized (trade) {
|
||||||
|
latchTrade();
|
||||||
|
this.errorMessageHandler = errorMessageHandler;
|
||||||
BuyerEvent event = BuyerEvent.PAYMENT_SENT;
|
BuyerEvent event = BuyerEvent.PAYMENT_SENT;
|
||||||
expect(phase(Trade.Phase.DEPOSIT_UNLOCKED)
|
expect(phase(Trade.Phase.DEPOSIT_UNLOCKED)
|
||||||
.with(event)
|
.with(event)
|
||||||
|
@ -139,15 +141,16 @@ public abstract class BuyerProtocol extends DisputeProtocol {
|
||||||
BuyerSendsPaymentSentMessage.class) // don't latch trade because this blocks and runs in background
|
BuyerSendsPaymentSentMessage.class) // don't latch trade because this blocks and runs in background
|
||||||
.using(new TradeTaskRunner(trade,
|
.using(new TradeTaskRunner(trade,
|
||||||
() -> {
|
() -> {
|
||||||
|
this.errorMessageHandler = null;
|
||||||
resultHandler.handleResult();
|
resultHandler.handleResult();
|
||||||
handleTaskRunnerSuccess(event);
|
handleTaskRunnerSuccess(event);
|
||||||
},
|
},
|
||||||
(errorMessage) -> {
|
(errorMessage) -> {
|
||||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
|
||||||
handleTaskRunnerFault(event, errorMessage);
|
handleTaskRunnerFault(event, errorMessage);
|
||||||
})))
|
})))
|
||||||
.run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_PAYMENT_SENT))
|
.run(() -> trade.setState(Trade.State.BUYER_CONFIRMED_IN_UI_PAYMENT_SENT))
|
||||||
.executeTasks();
|
.executeTasks();
|
||||||
|
awaitTradeLatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,14 +172,11 @@ public abstract class BuyerProtocol extends DisputeProtocol {
|
||||||
BuyerProcessesPaymentReceivedMessage.class)
|
BuyerProcessesPaymentReceivedMessage.class)
|
||||||
.using(new TradeTaskRunner(trade,
|
.using(new TradeTaskRunner(trade,
|
||||||
() -> {
|
() -> {
|
||||||
stopTimeout();
|
|
||||||
handleTaskRunnerSuccess(peer, message);
|
handleTaskRunnerSuccess(peer, message);
|
||||||
},
|
},
|
||||||
errorMessage -> {
|
errorMessage -> {
|
||||||
stopTimeout();
|
|
||||||
handleTaskRunnerFault(peer, message, errorMessage);
|
handleTaskRunnerFault(peer, message, errorMessage);
|
||||||
}))
|
})))
|
||||||
.withTimeout(TRADE_TIMEOUT))
|
|
||||||
.executeTasks(true);
|
.executeTasks(true);
|
||||||
awaitTradeLatch();
|
awaitTradeLatch();
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,6 +125,8 @@ public abstract class SellerProtocol extends DisputeProtocol {
|
||||||
public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
public void onPaymentReceived(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
log.info("SellerProtocol.onPaymentReceived()");
|
log.info("SellerProtocol.onPaymentReceived()");
|
||||||
synchronized (trade) {
|
synchronized (trade) {
|
||||||
|
latchTrade();
|
||||||
|
this.errorMessageHandler = errorMessageHandler;
|
||||||
SellerEvent event = SellerEvent.PAYMENT_RECEIVED;
|
SellerEvent event = SellerEvent.PAYMENT_RECEIVED;
|
||||||
expect(anyPhase(Trade.Phase.PAYMENT_SENT, Trade.Phase.PAYMENT_RECEIVED)
|
expect(anyPhase(Trade.Phase.PAYMENT_SENT, Trade.Phase.PAYMENT_RECEIVED)
|
||||||
.with(event)
|
.with(event)
|
||||||
|
@ -135,14 +137,15 @@ public abstract class SellerProtocol extends DisputeProtocol {
|
||||||
SellerPreparesPaymentReceivedMessage.class,
|
SellerPreparesPaymentReceivedMessage.class,
|
||||||
SellerSendsPaymentReceivedMessage.class)
|
SellerSendsPaymentReceivedMessage.class)
|
||||||
.using(new TradeTaskRunner(trade, () -> {
|
.using(new TradeTaskRunner(trade, () -> {
|
||||||
|
this.errorMessageHandler = null;
|
||||||
resultHandler.handleResult();
|
resultHandler.handleResult();
|
||||||
handleTaskRunnerSuccess(event);
|
handleTaskRunnerSuccess(event);
|
||||||
}, (errorMessage) -> {
|
}, (errorMessage) -> {
|
||||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
|
||||||
handleTaskRunnerFault(event, errorMessage);
|
handleTaskRunnerFault(event, errorMessage);
|
||||||
})))
|
})))
|
||||||
.run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT))
|
.run(() -> trade.setState(Trade.State.SELLER_CONFIRMED_IN_UI_PAYMENT_RECEIPT))
|
||||||
.executeTasks();
|
.executeTasks();
|
||||||
|
awaitTradeLatch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,11 +115,7 @@ class GrpcTradesService extends TradesImplBase {
|
||||||
@Override
|
@Override
|
||||||
public void takeOffer(TakeOfferRequest req,
|
public void takeOffer(TakeOfferRequest req,
|
||||||
StreamObserver<TakeOfferReply> responseObserver) {
|
StreamObserver<TakeOfferReply> responseObserver) {
|
||||||
GrpcErrorMessageHandler errorMessageHandler =
|
GrpcErrorMessageHandler errorMessageHandler = new GrpcErrorMessageHandler(getTakeOfferMethod().getFullMethodName(), responseObserver, exceptionHandler, log);
|
||||||
new GrpcErrorMessageHandler(getTakeOfferMethod().getFullMethodName(),
|
|
||||||
responseObserver,
|
|
||||||
exceptionHandler,
|
|
||||||
log);
|
|
||||||
try {
|
try {
|
||||||
coreApi.takeOffer(req.getOfferId(),
|
coreApi.takeOffer(req.getOfferId(),
|
||||||
req.getPaymentAccountId(),
|
req.getPaymentAccountId(),
|
||||||
|
@ -144,12 +140,19 @@ class GrpcTradesService extends TradesImplBase {
|
||||||
@Override
|
@Override
|
||||||
public void confirmPaymentStarted(ConfirmPaymentStartedRequest req,
|
public void confirmPaymentStarted(ConfirmPaymentStartedRequest req,
|
||||||
StreamObserver<ConfirmPaymentStartedReply> responseObserver) {
|
StreamObserver<ConfirmPaymentStartedReply> responseObserver) {
|
||||||
|
GrpcErrorMessageHandler errorMessageHandler = new GrpcErrorMessageHandler(getConfirmPaymentStartedMethod().getFullMethodName(), responseObserver, exceptionHandler, log);
|
||||||
try {
|
try {
|
||||||
coreApi.confirmPaymentStarted(req.getTradeId());
|
coreApi.confirmPaymentStarted(req.getTradeId(),
|
||||||
var reply = ConfirmPaymentStartedReply.newBuilder().build();
|
() -> {
|
||||||
responseObserver.onNext(reply);
|
var reply = ConfirmPaymentStartedReply.newBuilder().build();
|
||||||
responseObserver.onCompleted();
|
responseObserver.onNext(reply);
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
},
|
||||||
|
errorMessage -> {
|
||||||
|
if (!errorMessageHandler.isErrorHandled()) errorMessageHandler.handleErrorMessage(errorMessage);
|
||||||
|
});
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
|
cause.printStackTrace();
|
||||||
exceptionHandler.handleException(log, cause, responseObserver);
|
exceptionHandler.handleException(log, cause, responseObserver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,12 +160,19 @@ class GrpcTradesService extends TradesImplBase {
|
||||||
@Override
|
@Override
|
||||||
public void confirmPaymentReceived(ConfirmPaymentReceivedRequest req,
|
public void confirmPaymentReceived(ConfirmPaymentReceivedRequest req,
|
||||||
StreamObserver<ConfirmPaymentReceivedReply> responseObserver) {
|
StreamObserver<ConfirmPaymentReceivedReply> responseObserver) {
|
||||||
|
GrpcErrorMessageHandler errorMessageHandler = new GrpcErrorMessageHandler(getConfirmPaymentReceivedMethod().getFullMethodName(), responseObserver, exceptionHandler, log);
|
||||||
try {
|
try {
|
||||||
coreApi.confirmPaymentReceived(req.getTradeId());
|
coreApi.confirmPaymentReceived(req.getTradeId(),
|
||||||
var reply = ConfirmPaymentReceivedReply.newBuilder().build();
|
() -> {
|
||||||
responseObserver.onNext(reply);
|
var reply = ConfirmPaymentReceivedReply.newBuilder().build();
|
||||||
responseObserver.onCompleted();
|
responseObserver.onNext(reply);
|
||||||
|
responseObserver.onCompleted();
|
||||||
|
},
|
||||||
|
errorMessage -> {
|
||||||
|
if (!errorMessageHandler.isErrorHandled()) errorMessageHandler.handleErrorMessage(errorMessage);
|
||||||
|
});
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
|
cause.printStackTrace();
|
||||||
exceptionHandler.handleException(log, cause, responseObserver);
|
exceptionHandler.handleException(log, cause, responseObserver);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue