add logging and popup when trade wallet returns null txs

This commit is contained in:
woodser 2024-05-24 10:15:05 -04:00
parent b63227e8db
commit 3e2206cf5e
3 changed files with 41 additions and 12 deletions

View file

@ -94,6 +94,7 @@ import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import monero.common.MoneroRpcConnection; import monero.common.MoneroRpcConnection;
import monero.common.MoneroUtils;
import monero.common.TaskLooper; import monero.common.TaskLooper;
import monero.daemon.MoneroDaemon; import monero.daemon.MoneroDaemon;
import monero.daemon.model.MoneroKeyImage; import monero.daemon.model.MoneroKeyImage;
@ -1082,16 +1083,40 @@ public abstract class Trade implements Tradable, Model {
private MoneroTxWallet doCreatePayoutTx() { private MoneroTxWallet doCreatePayoutTx() {
// check if multisig import needed // check if multisig import needed
MoneroWallet multisigWallet = getWallet(); if (wallet.isMultisigImportNeeded()) throw new RuntimeException("Cannot create payout tx because multisig import is needed");
if (multisigWallet.isMultisigImportNeeded()) throw new RuntimeException("Cannot create payout tx because multisig import is needed");
// gather info // gather info
String sellerPayoutAddress = this.getSeller().getPayoutAddressString(); String sellerPayoutAddress = this.getSeller().getPayoutAddressString();
String buyerPayoutAddress = this.getBuyer().getPayoutAddressString(); String buyerPayoutAddress = this.getBuyer().getPayoutAddressString();
Preconditions.checkNotNull(sellerPayoutAddress, "Seller payout address must not be null"); Preconditions.checkNotNull(sellerPayoutAddress, "Seller payout address must not be null");
Preconditions.checkNotNull(buyerPayoutAddress, "Buyer payout address must not be null"); Preconditions.checkNotNull(buyerPayoutAddress, "Buyer payout address must not be null");
BigInteger sellerDepositAmount = multisigWallet.getTx(this.getSeller().getDepositTxHash()).getIncomingAmount();
BigInteger buyerDepositAmount = multisigWallet.getTx(this.getBuyer().getDepositTxHash()).getIncomingAmount(); // TODO: wallet query to get deposit txs can sometimes return null, maybe when disconnected?
if (wallet.getTx(getSeller().getDepositTxHash()) == null || wallet.getTx(getBuyer().getDepositTxHash()) == null) {
String warningMsg = "Issue detected with trade wallet " + getShortId() + ". Please send logs to Haveno developers and restart your application if you encounter further problems:";
warningMsg += "\n\nSeller deposit tx id: " + getSeller().getDepositTxHash();
warningMsg += "\nBuyer deposit tx id: " + getBuyer().getDepositTxHash();
warningMsg += "\nSeller deposit tx is initialized: " + (getSeller().getDepositTx() != null);
warningMsg += "\nBuyer deposit tx is initialized: " + (getBuyer().getDepositTx() != null);
log.warn(warningMsg);
// request with logging
int previousLogLevel = MoneroUtils.getLogLevel();
MoneroUtils.setLogLevel(3);
log.warn("Requesting seller tx with logging");
MoneroTxWallet fetchedTx = wallet.getTx(getSeller().getDepositTxHash());
log.info("Seller tx: " + fetchedTx);
log.warn("Requesting buyer tx with logging");
fetchedTx = wallet.getTx(getBuyer().getDepositTxHash());
log.info("Buyer tx: " + fetchedTx);
MoneroUtils.setLogLevel(previousLogLevel);
// set top level error message to notify user
HavenoUtils.havenoSetup.getTopErrorMsg().set(warningMsg);
}
BigInteger sellerDepositAmount = getSeller().getDepositTx().getIncomingAmount();
BigInteger buyerDepositAmount = getBuyer().getDepositTx().getIncomingAmount();
BigInteger tradeAmount = getAmount(); BigInteger tradeAmount = getAmount();
BigInteger buyerPayoutAmount = buyerDepositAmount.add(tradeAmount); BigInteger buyerPayoutAmount = buyerDepositAmount.add(tradeAmount);
BigInteger sellerPayoutAmount = sellerDepositAmount.subtract(tradeAmount); BigInteger sellerPayoutAmount = sellerDepositAmount.subtract(tradeAmount);
@ -1112,7 +1137,7 @@ public abstract class Trade implements Tradable, Model {
getBuyer().setPayoutAmount(HavenoUtils.getDestination(buyerPayoutAddress, payoutTx).getAmount()); getBuyer().setPayoutAmount(HavenoUtils.getDestination(buyerPayoutAddress, payoutTx).getAmount());
getSeller().setPayoutTxFee(payoutTxFeeSplit); getSeller().setPayoutTxFee(payoutTxFeeSplit);
getSeller().setPayoutAmount(HavenoUtils.getDestination(sellerPayoutAddress, payoutTx).getAmount()); getSeller().setPayoutAmount(HavenoUtils.getDestination(sellerPayoutAddress, payoutTx).getAmount());
getSelf().setUpdatedMultisigHex(multisigWallet.exportMultisigHex()); getSelf().setUpdatedMultisigHex(wallet.exportMultisigHex());
return payoutTx; return payoutTx;
} }
@ -1147,8 +1172,8 @@ public abstract class Trade implements Tradable, Model {
// gather relevant info // gather relevant info
MoneroWallet wallet = getWallet(); MoneroWallet wallet = getWallet();
Contract contract = getContract(); Contract contract = getContract();
BigInteger sellerDepositAmount = wallet.getTx(getSeller().getDepositTxHash()).getIncomingAmount(); // TODO (woodser): redundancy of processModel.getPreparedDepositTxId() vs this.getDepositTxId() necessary or avoidable? BigInteger sellerDepositAmount = getSeller().getDepositTx().getIncomingAmount();
BigInteger buyerDepositAmount = wallet.getTx(getBuyer().getDepositTxHash()).getIncomingAmount(); BigInteger buyerDepositAmount = getBuyer().getDepositTx().getIncomingAmount();
BigInteger tradeAmount = getAmount(); BigInteger tradeAmount = getAmount();
// describe payout tx // describe payout tx
@ -2283,6 +2308,10 @@ public abstract class Trade implements Tradable, Model {
private void pollWallet() { private void pollWallet() {
if (pollInProgress) return; if (pollInProgress) return;
doPollWallet();
}
private void doPollWallet() {
synchronized (pollLock) { synchronized (pollLock) {
pollInProgress = true; pollInProgress = true;
try { try {
@ -2424,8 +2453,8 @@ public abstract class Trade implements Tradable, Model {
return walletHeight.get() < xmrConnectionService.getTargetHeight(); return walletHeight.get() < xmrConnectionService.getTargetHeight();
} }
private void setDepositTxs(List<? extends MoneroTx> txs) { private void setDepositTxs(List<MoneroTxWallet> txs) {
for (MoneroTx tx : txs) { for (MoneroTxWallet tx : txs) {
if (tx.getHash().equals(getMaker().getDepositTxHash())) getMaker().setDepositTx(tx); if (tx.getHash().equals(getMaker().getDepositTxHash())) getMaker().setDepositTx(tx);
if (tx.getHash().equals(getTaker().getDepositTxHash())) getTaker().setDepositTx(tx); if (tx.getHash().equals(getTaker().getDepositTxHash())) getTaker().setDepositTx(tx);
} }

View file

@ -33,7 +33,7 @@ import haveno.network.p2p.NodeAddress;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import monero.daemon.model.MoneroTx; import monero.wallet.model.MoneroTxWallet;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger; import java.math.BigInteger;
@ -56,7 +56,7 @@ public final class TradePeer implements PersistablePayload {
@Setter @Setter
@Nullable @Nullable
transient private byte[] preparedDepositTx; transient private byte[] preparedDepositTx;
transient private MoneroTx depositTx; transient private MoneroTxWallet depositTx;
// Persistable mutable // Persistable mutable
@Nullable @Nullable

View file

@ -118,6 +118,7 @@ public class XmrWalletService {
public static final String MONERO_WALLET_RPC_PATH = MONERO_BINS_DIR + File.separator + MONERO_WALLET_RPC_NAME; public static final String MONERO_WALLET_RPC_PATH = MONERO_BINS_DIR + File.separator + MONERO_WALLET_RPC_NAME;
public static final double MINER_FEE_TOLERANCE = 0.25; // miner fee must be within percent of estimated fee public static final double MINER_FEE_TOLERANCE = 0.25; // miner fee must be within percent of estimated fee
public static final MoneroTxPriority PROTOCOL_FEE_PRIORITY = MoneroTxPriority.ELEVATED; public static final MoneroTxPriority PROTOCOL_FEE_PRIORITY = MoneroTxPriority.ELEVATED;
public static final int MONERO_LOG_LEVEL = -1; // monero library log level, -1 to disable
private static final MoneroNetworkType MONERO_NETWORK_TYPE = getMoneroNetworkType(); private static final MoneroNetworkType MONERO_NETWORK_TYPE = getMoneroNetworkType();
private static final MoneroWalletRpcManager MONERO_WALLET_RPC_MANAGER = new MoneroWalletRpcManager(); private static final MoneroWalletRpcManager MONERO_WALLET_RPC_MANAGER = new MoneroWalletRpcManager();
private static final String MONERO_WALLET_RPC_USERNAME = "haveno_user"; private static final String MONERO_WALLET_RPC_USERNAME = "haveno_user";
@ -126,7 +127,6 @@ public class XmrWalletService {
private static final String KEYS_FILE_POSTFIX = ".keys"; private static final String KEYS_FILE_POSTFIX = ".keys";
private static final String ADDRESS_FILE_POSTFIX = ".address.txt"; private static final String ADDRESS_FILE_POSTFIX = ".address.txt";
private static final int NUM_MAX_WALLET_BACKUPS = 1; private static final int NUM_MAX_WALLET_BACKUPS = 1;
private static final int MONERO_LOG_LEVEL = -1; // monero library log level, -1 to disable
private static final int MAX_SYNC_ATTEMPTS = 3; private static final int MAX_SYNC_ATTEMPTS = 3;
private static final boolean PRINT_RPC_STACK_TRACE = false; private static final boolean PRINT_RPC_STACK_TRACE = false;
private static final String THREAD_ID = XmrWalletService.class.getSimpleName(); private static final String THREAD_ID = XmrWalletService.class.getSimpleName();